├── .gitattributes
├── .gitignore
├── LICENSE.txt
├── ProtocolGateway.Standard.sln
├── ProtocolGateway.sln
├── ProtocolGateway.sln.DotSettings
├── README.md
├── RELEASE_NOTES.md
├── SECURITY.md
├── build.cmd
├── docs
└── DeveloperGuide.md
├── host
├── ProtocolGateway.Host.Cloud.Service
│ ├── GCSettingsManagement.ps1
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── ProtocolGateway.Host.Cloud.Service.csproj
│ ├── RoleEnvironmentSettingsProvider.cs
│ ├── Startup.cmd
│ ├── WorkerRole.cs
│ ├── app.config
│ └── packages.config
├── ProtocolGateway.Host.Cloud
│ ├── ProtocolGateway.Host.Cloud.ServiceContent
│ │ └── diagnostics.wadcfgx
│ ├── ProtocolGateway.Host.Cloud.ccproj
│ ├── ServiceConfiguration.Cloud.cscfg
│ ├── ServiceConfiguration.Local.cscfg
│ └── ServiceDefinition.csdef
├── ProtocolGateway.Host.Common
│ ├── AcceptLimiter.cs
│ ├── AcceptLimiterTlsReleaseHandler.cs
│ ├── Bootstrapper.cs
│ ├── BootstrapperEventSource.cs
│ ├── MqttPacketPayloadCompressionHandler.cs
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── ProtocolGateway.Host.Common.NetStandard.csproj
│ ├── ProtocolGateway.Host.Common.csproj
│ ├── app.config
│ └── packages.config
├── ProtocolGateway.Host.Console.NetStandard
│ ├── ConsoleEventListener.cs
│ ├── Program.cs
│ ├── ProtocolGateway.Host.Console.NetStandard.csproj
│ └── appSettings.json
├── ProtocolGateway.Host.Console
│ ├── App.config
│ ├── Program.cs
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── ProtocolGateway.Host.Console.csproj
│ ├── appSettings.config.user
│ └── packages.config
├── ProtocolGateway.Host.Fabric.FrontEnd
│ ├── App.config
│ ├── FrontEnd.cs
│ ├── PackageRoot
│ │ ├── Code
│ │ │ ├── InstallDotNet48.ps1
│ │ │ ├── setup.cmd
│ │ │ └── setup.ps1
│ │ ├── Config
│ │ │ ├── FrontEnd.AzureState.json
│ │ │ ├── FrontEnd.IoTHubClient.json
│ │ │ ├── FrontEnd.Mqtt.json
│ │ │ ├── FrontEnd.json
│ │ │ └── Settings.xml
│ │ └── ServiceManifest.xml
│ ├── Program.cs
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── ProtocolGateway.Host.Fabric.FrontEnd.csproj
│ ├── configuration
│ │ ├── AzureSessionStateConfiguration.cs
│ │ ├── GatewayConfiguration.cs
│ │ ├── IoTHubConfiguration.cs
│ │ ├── MqttServiceConfiguration.cs
│ │ └── ServiceFabricConfigurationProvider.cs
│ ├── logging
│ │ ├── Logger.cs
│ │ └── ServiceLogger.cs
│ ├── mqtt
│ │ └── MqttCommunicationListener.cs
│ └── packages.config
├── ProtocolGateway.Host.Fabric
│ ├── ApplicationPackageRoot
│ │ └── ApplicationManifest.xml
│ ├── ApplicationParameters
│ │ ├── Cloud.xml
│ │ ├── Local.1Node.xml
│ │ └── Local.5Node.xml
│ ├── ProtocolGateway.Host.Fabric.sfproj
│ ├── PublishProfiles
│ │ └── Cloud.xml
│ ├── Scripts
│ │ └── Deploy-FabricApplication.ps1
│ ├── app.config
│ └── packages.config
├── Walkthrough.md
├── deploy.ps1
├── fabricsetup
│ └── ProtocolGateway.Host.FabricSetup.CounterSetup
│ │ ├── App.config
│ │ ├── Program.cs
│ │ ├── Properties
│ │ └── AssemblyInfo.cs
│ │ ├── ProtocolGateway.Host.FabricSetup.CounterSetup.csproj
│ │ └── logging
│ │ └── StartupLogger.cs
├── fabricshared
│ ├── ProtocolGateway.Host.Fabric.FabricShared.Configuration
│ │ ├── ConfigurationChangedEventArgs.cs
│ │ ├── ConfigurationProvider.cs
│ │ ├── IConfigurationProvider.cs
│ │ ├── Properties
│ │ │ ├── AssemblyInfo.cs
│ │ │ ├── Resources.Designer.cs
│ │ │ └── Resources.resx
│ │ ├── ProtocolGateway.Host.Fabric.FabricShared.Configuration.csproj
│ │ ├── app.config
│ │ └── packages.config
│ ├── ProtocolGateway.Host.Fabric.FabricShared.Health
│ │ ├── HealthReporter.cs
│ │ ├── MetricReporter.cs
│ │ ├── Properties
│ │ │ └── AssemblyInfo.cs
│ │ ├── ProtocolGateway.Host.Fabric.FabricShared.Health.csproj
│ │ └── packages.config
│ ├── ProtocolGateway.Host.Fabric.FabricShared.Logging
│ │ ├── ExceptionExtensions.cs
│ │ ├── ILogger.cs
│ │ ├── IServiceLogger.cs
│ │ ├── LoggerBase.cs
│ │ ├── Properties
│ │ │ └── AssemblyInfo.cs
│ │ ├── ProtocolGateway.Host.Fabric.FabricShared.Logging.csproj
│ │ ├── ServiceLoggerBase.cs
│ │ └── packages.config
│ └── ProtocolGateway.Host.Fabric.FabricShared.Security
│ │ ├── CertificateUtilities.cs
│ │ ├── Properties
│ │ └── AssemblyInfo.cs
│ │ ├── ProtocolGateway.Host.Fabric.FabricShared.Security.csproj
│ │ └── SecureStringExtensions.cs
└── shared
│ └── protocol-gateway.contoso.com.pfx
├── src
├── ProtocolGateway.Core
│ ├── AppConfigSettingsProvider.cs
│ ├── ConfigManagerReader.cs
│ ├── ConfigurationErrorsException.cs
│ ├── ConfigurationExtensionReader.cs
│ ├── ErrorCode.cs
│ ├── Extensions
│ │ └── TaskExtensions.cs
│ ├── IAppConfigReader.cs
│ ├── ISettingsProvider.cs
│ ├── Identity
│ │ ├── IDeviceIdentity.cs
│ │ ├── IDeviceIdentityProvider.cs
│ │ └── UnauthenticatedDeviceIdentity.cs
│ ├── Instrumentation
│ │ ├── AveragePerformanceCounter.cs
│ │ ├── CommonEventSource.cs
│ │ ├── EmptyPerformanceCounter.cs
│ │ ├── EmptyPerformanceCounterManager.cs
│ │ ├── IPerformanceCounter.cs
│ │ ├── IPerformanceCounterManager.cs
│ │ ├── PerformanceCounterCategoryInfo.cs
│ │ ├── PerformanceCounters.cs
│ │ ├── SafePerformanceCounter.cs
│ │ └── WindowsPerformanceCounterManager.cs
│ ├── Messaging
│ │ ├── IBatchAwareMessagingServiceClient.cs
│ │ ├── IMessage.cs
│ │ ├── IMessagingBridge.cs
│ │ ├── IMessagingChannel.cs
│ │ ├── IMessagingServiceClient.cs
│ │ ├── IMessagingSource.cs
│ │ ├── Message.cs
│ │ └── MessagingException.cs
│ ├── Mqtt
│ │ ├── AckPendingMessageState.cs
│ │ ├── ChannelMessageProcessingException.cs
│ │ ├── CompletionPendingMessageState.cs
│ │ ├── IMessageProcessor.cs
│ │ ├── IPacketReference.cs
│ │ ├── MessageAsyncProcessor.cs
│ │ ├── MessageAsyncProcessorBase.cs
│ │ ├── MessageBatchAsyncProcessor.cs
│ │ ├── MessageFeedbackChannel.cs
│ │ ├── MessagePropertyNames.cs
│ │ ├── MessageTypes.cs
│ │ ├── MessagingBridgeFactoryFunc.cs
│ │ ├── MqttAdapter.cs
│ │ ├── Persistence
│ │ │ ├── IQoS2MessageDeliveryState.cs
│ │ │ ├── IQos2StatePersistenceProvider.cs
│ │ │ ├── ISessionState.cs
│ │ │ ├── ISessionStatePersistenceProvider.cs
│ │ │ ├── ISubscription.cs
│ │ │ ├── TransientSessionState.cs
│ │ │ ├── TransientSessionStatePersistenceProvider.cs
│ │ │ └── TransientSubscription.cs
│ │ ├── RequestAckPairProcessor.cs
│ │ ├── Settings.cs
│ │ ├── TemplateParameters.cs
│ │ └── Util.cs
│ ├── Properties
│ │ ├── AssemblyInfo.cs
│ │ └── Friends.cs
│ ├── ProtocolGateway.Core.NetStandard.csproj
│ ├── ProtocolGateway.Core.csproj
│ ├── ProtocolGatewayException.cs
│ ├── UriPathTemplate.cs
│ ├── app.config
│ └── packages.config
├── ProtocolGateway.IotHubClient
│ ├── AuthenticationScope.cs
│ ├── CommandReceiver.cs
│ ├── DeviceClientRetryPolicy.cs
│ ├── Extensions.cs
│ ├── IMessageDispatcher.cs
│ ├── IotHubBridge.cs
│ ├── IotHubClientMessage.cs
│ ├── IotHubClientSettings.cs
│ ├── IotHubDeviceIdentity.cs
│ ├── KeyDeviceIdentityProvider.cs
│ ├── MethodHandler.cs
│ ├── Properties
│ │ ├── AssemblyInfo.cs
│ │ └── Friends.cs
│ ├── ProtocolGateway.IotHubClient.NetStandard.csproj
│ ├── ProtocolGateway.IotHubClient.csproj
│ ├── SasTokenDeviceIdentityProvider.cs
│ ├── SendMessageOutcome.cs
│ ├── TelemetrySender.cs
│ ├── TopicHandling.cs
│ ├── app.config
│ └── packages.config
├── ProtocolGateway.Providers.CloudStorage
│ ├── BlobSessionState.cs
│ ├── BlobSessionStatePersistenceProvider.cs
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── ProtocolGateway.Providers.CloudStorage.NetStandard.csproj
│ ├── ProtocolGateway.Providers.CloudStorage.csproj
│ ├── StorageBufferManager.cs
│ ├── Subscription.cs
│ ├── TableMessageDeliveryState.cs
│ ├── TableQos2StatePersistenceProvider.cs
│ ├── app.config
│ └── packages.config
└── SharedAssemblyInfo.cs
└── test
├── ProtocolGateway.Client.NetStandard
├── Program.cs
├── Properties
│ └── AssemblyInfo.cs
└── ProtocolGateway.Client.NetStandard.csproj
├── ProtocolGateway.Tests.Load
├── App.config
├── ConsoleLoggingHandler.cs
├── DeviceRunner.cs
├── EnumerableExtensions.cs
├── IdProvider.cs
├── OccasionalTelemetryRunner.cs
├── Options.cs
├── Program.cs
├── Properties
│ └── AssemblyInfo.cs
├── ProtocolGateway.Tests.Load.csproj
├── RunnerConfiguration.cs
├── RunnerHost.cs
├── StableTelemetryRunner.cs
├── TaskExtensions.cs
└── packages.config
└── ProtocolGateway.Tests
├── ChannelExtensions.cs
├── DiagnosticsTests.cs
├── EndToEndTests.cs
├── Extensions
├── ByteBufferExtensions.cs
└── TaskExtensions.cs
├── MqttTopicMatchingTests.cs
├── Properties
└── AssemblyInfo.cs
├── ProtocolGateway.Tests.csproj
├── ReadListeningHandler.cs
├── XUnitLoggingHandler.cs
├── XUnitOutputSink.cs
├── app.config
├── appSettings.config.user
├── mqttTopicConversion.config.user
├── packages.config
└── tlscert.pfx
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.doc diff=astextplain
2 | *.DOC diff=astextplain
3 | *.docx diff=astextplain
4 | *.DOCX diff=astextplain
5 | *.dot diff=astextplain
6 | *.DOT diff=astextplain
7 | *.pdf diff=astextplain
8 | *.PDF diff=astextplain
9 | *.rtf diff=astextplain
10 | *.RTF diff=astextplain
11 |
12 | *.jpg binary
13 | *.png binary
14 | *.gif binary
15 |
16 | *.cs text=auto diff=csharp
17 | *.vb text=auto
18 | *.resx text=auto
19 | *.c text=auto
20 | *.cpp text=auto
21 | *.cxx text=auto
22 | *.h text=auto
23 | *.hxx text=auto
24 | *.py text=auto
25 | *.rb text=auto
26 | *.java text=auto
27 | *.html text=auto
28 | *.htm text=auto
29 | *.css text=auto
30 | *.scss text=auto
31 | *.sass text=auto
32 | *.less text=auto
33 | *.js text=auto
34 | *.lisp text=auto
35 | *.clj text=auto
36 | *.sql text=auto
37 | *.php text=auto
38 | *.lua text=auto
39 | *.m text=auto
40 | *.asm text=auto
41 | *.erl text=auto
42 | *.fs text=auto
43 | *.fsx text=auto
44 | *.hs text=auto
45 |
46 | *.csproj text=auto
47 | *.vbproj text=auto
48 | *.fsproj text=auto
49 | *.dbproj text=auto
50 | *.sln text=auto eol=crlf
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | [Oo]bj/
2 | [Bb]in/
3 | TestResults/
4 | .nuget/
5 | _ReSharper.*/
6 | *.exe
7 | packages/
8 | artifacts/
9 | PublishProfiles/
10 | csx/
11 | *.user
12 | *.suo
13 | *.cache
14 | *.docstates
15 | _ReSharper.*
16 | nuget.exe
17 | *net45.csproj
18 | *net451.csproj
19 | *k10.csproj
20 | *.psess
21 | *.vsp
22 | .vs/
23 | *.pidb
24 | *.userprefs
25 | *DS_Store
26 | *.ncrunchsolution
27 | *.*sdf
28 | *.ipch
29 | *.sln.ide
30 | *.lock.json
31 | *.db
32 | .idea.*/
33 | .vscode/*
34 | secrets/
35 | host/ProtocolGateway.Host.Fabric/pkg/*
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) Microsoft Corporation
2 | All rights reserved.
3 |
4 | MIT License
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
--------------------------------------------------------------------------------
/RELEASE_NOTES.md:
--------------------------------------------------------------------------------
1 | #### 3.0.0 July 24, 2019
2 | - Change the way `MqttAdapter` handles transient sessions. `MqttAdapter.ProcessPendingSubscriptionChanges` will now always call `ISessionStatePersistenceProvider.SetAsync` irrespective of the session being transient or not. State handling of transient sessions is now left to the implementation of '`ISessionStatePersistenceProvider`
3 | - `BlobSessionStatePersistenceProvider.SetAsync` will return instead of throwing if the state is transient
4 |
5 | #### 1.0.1 March 12
6 | - Azure Table QoS 2 persistence provider uses proper query API to retrieve only relevant row.
7 | - QoS 2 persistence provider API is modified to work with SequenceNumber instead of MessageId.
8 | - Azure Blob session state persistence provider is modified to update ETag value on in-memory session state object to allow saving it later on without any issue.
9 | - 14 least significant bits are used when converting SequenceNumber into PacketId.
10 | - `IMessage.SequenceNumber` type is changed to ulong.
11 |
12 | #### 1.0.0 March 03
13 | - `IQos2StatePersistenceProvider` now accepts device identity to scope messages in flight to device level.
14 | - `IAuthenticationProvider` has been renamed into `IDeviceIdentityProvider` and the API has changed to allow for a flexible interaction between device identity source and other protocol gateway components.
15 | - `ITopicNameRouter` has been renamed into `IMessageRouter` and the API generalized to work with the message as a whole.
16 | - `IDeviceClient` has been renamed into `IMessagingServiceClient` to better reflect the purpose of the component. `IMessagingFactory` was introduced and message exchange with `IMessagingServiceClient` is done using `IMessage` objects.
17 | - Issues #23, #26, #27, #28, #33 have been addressed.
18 | - Microsoft Azure IoT SDK specific components have been moved to `ProtocolGateway.IotHubClient` project.
19 | - Components are now released as 3 nuget packages according to certain dependencies (Azure Storage, Azure IoT SDK):
20 | - `Microsoft.Azure.Devices.ProtocolGateway.Core`,
21 | - `Microsoft.Azure.Devices.ProtocolGateway.IotHubClient`,
22 | - `Microsoft.Azure.Devices.ProtocolGateway.Providers.CloudStorage`.
23 | - Renamed `samples` into `host` throughout the solution.
24 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ## Security
4 |
5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
6 |
7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below.
8 |
9 | ## Reporting Security Issues
10 |
11 | **Please do not report security vulnerabilities through public GitHub issues.**
12 |
13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report).
14 |
15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey).
16 |
17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc).
18 |
19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
20 |
21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
22 | * Full paths of source file(s) related to the manifestation of the issue
23 | * The location of the affected source code (tag/branch/commit or direct URL)
24 | * Any special configuration required to reproduce the issue
25 | * Step-by-step instructions to reproduce the issue
26 | * Proof-of-concept or exploit code (if possible)
27 | * Impact of the issue, including how an attacker might exploit the issue
28 |
29 | This information will help us triage your report more quickly.
30 |
31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs.
32 |
33 | ## Preferred Languages
34 |
35 | We prefer all communications to be in English.
36 |
37 | ## Policy
38 |
39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd).
40 |
41 |
42 |
--------------------------------------------------------------------------------
/build.cmd:
--------------------------------------------------------------------------------
1 | @echo off
2 | cd %~dp0
3 |
4 | SETLOCAL
5 | SET CACHED_NUGET=%LocalAppData%\NuGet\NuGet.exe
6 |
7 | IF EXIST %CACHED_NUGET% goto vsvarssetup
8 | echo Downloading latest version of NuGet.exe...
9 | IF NOT EXIST %LocalAppData%\NuGet md %LocalAppData%\NuGet
10 | @powershell -NoProfile -ExecutionPolicy unrestricted -Command "$ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest 'https://www.nuget.org/nuget.exe' -OutFile '%CACHED_NUGET%'"
11 |
12 | :vsvarssetup
13 | if not defined VS120COMNTOOLS goto build
14 | if not exist "%VS120COMNTOOLS%\VsDevCmd.bat" goto build
15 | call "%VS120COMNTOOLS%\VsDevCmd.bat"
16 |
17 | :build
18 | %CACHED_NUGET% restore
19 | msbuild ProtocolGateway.sln
--------------------------------------------------------------------------------
/host/ProtocolGateway.Host.Cloud.Service/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | using System.Reflection;
5 | using System.Runtime.InteropServices;
6 |
7 | // General Information about an assembly is controlled through the following
8 | // set of attributes. Change these attribute values to modify the information
9 | // associated with an assembly.
10 |
11 | [assembly: AssemblyTitle("Microsoft.Azure.Devices.ProtocolGateway.Cloud.Host")]
12 | [assembly: AssemblyDescription("")]
13 | [assembly: AssemblyConfiguration("")]
14 | [assembly: AssemblyCompany("")]
15 | [assembly: AssemblyProduct("Microsoft.Azure.Devices.ProtocolGateway.Cloud.Host")]
16 | [assembly: AssemblyCopyright("Copyright © 2015")]
17 | [assembly: AssemblyTrademark("")]
18 | [assembly: AssemblyCulture("")]
19 |
20 | // Setting ComVisible to false makes the types in this assembly not visible
21 | // to COM components. If you need to access a type in this assembly from
22 | // COM, set the ComVisible attribute to true on that type.
23 |
24 | [assembly: ComVisible(false)]
25 |
26 | // The following GUID is for the ID of the typelib if this project is exposed to COM
27 |
28 | [assembly: Guid("ad7f0c70-3558-42be-a423-ddaeabe879fc")]
29 |
30 | // Version information for an assembly consists of the following four values:
31 | //
32 | // Major Version
33 | // Minor Version
34 | // Build Number
35 | // Revision
36 | //
37 | // You can specify all the values or you can default the Build and Revision Numbers
38 | // by using the '*' as shown below:
39 | // [assembly: AssemblyVersion("1.0.*")]
40 |
41 | [assembly: AssemblyVersion("1.0.0.0")]
42 | [assembly: AssemblyFileVersion("1.0.0.0")]
--------------------------------------------------------------------------------
/host/ProtocolGateway.Host.Cloud.Service/RoleEnvironmentSettingsProvider.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace ProtocolGateway.Host.Cloud.Service
5 | {
6 | using Microsoft.Azure.Devices.ProtocolGateway;
7 | using Microsoft.WindowsAzure.ServiceRuntime;
8 |
9 | public class RoleEnvironmentSettingsProvider : ISettingsProvider
10 | {
11 | public bool TryGetSetting(string name, out string value)
12 | {
13 | try
14 | {
15 | value = RoleEnvironment.GetConfigurationSettingValue(name);
16 | return true;
17 | }
18 | catch (RoleEnvironmentException)
19 | {
20 | value = default(string);
21 | return false;
22 | }
23 | }
24 | }
25 | }
--------------------------------------------------------------------------------
/host/ProtocolGateway.Host.Cloud.Service/Startup.cmd:
--------------------------------------------------------------------------------
1 | REM *********************************************************
2 | REM
3 | REM Copyright (c) Microsoft. All rights reserved.
4 | REM This code is licensed under the Microsoft Public License.
5 | REM THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
6 | REM ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
7 | REM IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
8 | REM PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
9 | REM
10 | REM *********************************************************
11 |
12 | REM Check if the script is running in the Azure emulator and if so do not run
13 | if "%IsEmulated%"=="true" goto :PastGC
14 |
15 | if "%UseServerGC%"=="False" goto :ValidateBackground
16 | if "%UseServerGC%"=="0" goto :ValidateBackground
17 | set UseServerGC="True"
18 |
19 | :ValidateBackground
20 | if "%UseBackgroundGC%"=="False" goto :SetGC
21 | if "%UseBackgroundGC%"=="0" goto :SetGC
22 | set UseBackgroundGC="True"
23 |
24 | :SetGC
25 | PowerShell.exe -executionpolicy unrestricted -command ".\GCSettingsManagement.ps1" -serverGC %UseServerGC% -backgroundGC %UseBackgroundGC%
26 |
27 | :PastGC
28 | netsh int ipv4 set dynamicport tcp start=1025 num=64511
29 | netsh int ipv4 show dynamicport tcp
30 |
31 | exit /b
--------------------------------------------------------------------------------
/host/ProtocolGateway.Host.Cloud/ServiceConfiguration.Cloud.cscfg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/host/ProtocolGateway.Host.Cloud/ServiceConfiguration.Local.cscfg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/host/ProtocolGateway.Host.Cloud/ServiceDefinition.csdef:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/host/ProtocolGateway.Host.Common/AcceptLimiter.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace ProtocolGateway.Host.Common
5 | {
6 | using System.Threading;
7 | using DotNetty.Transport.Channels;
8 |
9 | ///
10 | /// Controls connection accept rate based on number of concurrent connections going through throttled initialization phase
11 | ///
12 | sealed class AcceptLimiter : ChannelHandlerAdapter
13 | {
14 | IChannelHandlerContext capturedContext;
15 | long available;
16 |
17 | public AcceptLimiter(long capacity)
18 | {
19 | this.available = capacity;
20 | }
21 |
22 | public override void ChannelActive(IChannelHandlerContext context)
23 | {
24 | this.capturedContext = context;
25 | base.ChannelActive(context);
26 | context.Read();
27 | }
28 |
29 | public override void ChannelRead(IChannelHandlerContext context, object message)
30 | {
31 | if (Volatile.Read(ref this.available) > 0)
32 | {
33 | context.Read();
34 | }
35 | base.ChannelRead(context, message);
36 | }
37 |
38 | public void Claim() => Interlocked.Decrement(ref this.available);
39 |
40 | public void ReleaseClaim()
41 | {
42 | Interlocked.Increment(ref this.available);
43 | this.capturedContext?.Read();
44 | }
45 | }
46 | }
--------------------------------------------------------------------------------
/host/ProtocolGateway.Host.Common/AcceptLimiterTlsReleaseHandler.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace ProtocolGateway.Host.Common
5 | {
6 | using DotNetty.Handlers.Tls;
7 | using DotNetty.Transport.Channels;
8 |
9 | sealed class AcceptLimiterTlsReleaseHandler : ChannelHandlerAdapter
10 | {
11 | readonly AcceptLimiter limiter;
12 | bool claimReturned;
13 |
14 | public AcceptLimiterTlsReleaseHandler(AcceptLimiter limiter)
15 | {
16 | this.limiter = limiter;
17 | }
18 |
19 | public override void ChannelActive(IChannelHandlerContext context)
20 | {
21 | this.limiter.Claim();
22 | base.ChannelActive(context);
23 | }
24 |
25 | public override void ChannelInactive(IChannelHandlerContext context)
26 | {
27 | this.ReleaseClaim();
28 | base.ChannelInactive(context);
29 | }
30 |
31 | public override void UserEventTriggered(IChannelHandlerContext context, object evt)
32 | {
33 | if (evt is TlsHandshakeCompletionEvent tls) // TLS handshake is done so we return claim
34 | {
35 | this.ReleaseClaim();
36 | context.Channel.Pipeline.Remove(this);
37 | }
38 | base.UserEventTriggered(context, evt);
39 | }
40 |
41 | void ReleaseClaim()
42 | {
43 | if (!this.claimReturned)
44 | {
45 | this.claimReturned = true;
46 | this.limiter.ReleaseClaim();
47 | }
48 | }
49 | }
50 | }
--------------------------------------------------------------------------------
/host/ProtocolGateway.Host.Common/BootstrapperEventSource.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace ProtocolGateway.Host.Common
5 | {
6 | using System;
7 | using System.Diagnostics.Tracing;
8 |
9 | [EventSource(
10 | Name = "IoT-ProtocolGateway-Bootstrapper",
11 | Guid = "e29735c9-6796-4228-ac96-9db40faB697a")]
12 | public class BootstrapperEventSource : EventSource
13 | {
14 | const int VerboseEventId = 1;
15 | const int InfoEventId = 2;
16 | const int WarningEventId = 3;
17 | const int ErrorEventId = 4;
18 |
19 | public static readonly BootstrapperEventSource Log = new BootstrapperEventSource();
20 |
21 | BootstrapperEventSource()
22 | {
23 | }
24 |
25 | public bool IsVerboseEnabled => this.IsEnabled(EventLevel.Verbose, EventKeywords.None);
26 |
27 | public bool IsInfoEnabled => this.IsEnabled(EventLevel.Informational, EventKeywords.None);
28 |
29 | public bool IsWarningEnabled => this.IsEnabled(EventLevel.Warning, EventKeywords.None);
30 |
31 | public bool IsErrorEnabled => this.IsEnabled(EventLevel.Error, EventKeywords.None);
32 |
33 | [Event(VerboseEventId, Level = EventLevel.Verbose)]
34 | public void Verbose(string message, string info) => this.WriteEvent(VerboseEventId, message, info);
35 |
36 | [Event(InfoEventId, Level = EventLevel.Informational)]
37 | public void Info(string message, string info) => this.WriteEvent(InfoEventId, message, info);
38 |
39 | [NonEvent]
40 | public void Warning(string message) => this.Warning(message, string.Empty);
41 |
42 | [NonEvent]
43 | public void Warning(string message, Exception exception) => this.Warning(message, exception?.ToString() ?? string.Empty);
44 |
45 | [Event(WarningEventId, Level = EventLevel.Warning)]
46 | public void Warning(string message, string exception) => this.WriteEvent(WarningEventId, message, exception);
47 |
48 | [NonEvent]
49 | public void Error(string message, Exception exception) => this.Error(message, exception?.ToString() ?? string.Empty);
50 |
51 | [Event(ErrorEventId, Level = EventLevel.Error)]
52 | public void Error(string message, string exception) => this.WriteEvent(ErrorEventId, message, exception);
53 | }
54 | }
--------------------------------------------------------------------------------
/host/ProtocolGateway.Host.Common/MqttPacketPayloadCompressionHandler.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace ProtocolGateway.Host.Common
5 | {
6 | using System.Diagnostics.Contracts;
7 | using System.IO;
8 | using System.IO.Compression;
9 | using System.Threading.Tasks;
10 | using DotNetty.Buffers;
11 | using DotNetty.Codecs.Mqtt.Packets;
12 | using DotNetty.Common.Utilities;
13 | using DotNetty.Transport.Channels;
14 |
15 | public class MqttPacketPayloadCompressionHandler : ChannelHandlerAdapter
16 | {
17 | public override void ChannelRead(IChannelHandlerContext context, object message)
18 | {
19 | var packet = message as PublishPacket;
20 | if (packet != null)
21 | {
22 | IByteBuffer result = ApplyCompression(packet.Payload, CompressionMode.Decompress);
23 | packet.Payload = result;
24 | }
25 | context.FireChannelRead(message);
26 | }
27 |
28 | public override Task WriteAsync(IChannelHandlerContext context, object message)
29 | {
30 | var packet = message as PublishPacket;
31 | if (packet != null)
32 | {
33 | IByteBuffer result = ApplyCompression(packet.Payload, CompressionMode.Compress);
34 | packet.Payload = result;
35 | }
36 | return context.WriteAsync(message);
37 | }
38 |
39 | static IByteBuffer ApplyCompression(IByteBuffer buffer, CompressionMode compressionMode)
40 | {
41 | try
42 | {
43 | using (var outputStream = new MemoryStream())
44 | {
45 | using (var gzipStream = new GZipStream(outputStream, compressionMode, true))
46 | {
47 | buffer.ReadBytes(gzipStream, buffer.ReadableBytes);
48 | }
49 |
50 | Contract.Assert(outputStream.Length <= int.MaxValue);
51 |
52 | #if NETSTANDARD1_3
53 | return Unpooled.WrappedBuffer(outputStream.ToArray());
54 | #else
55 | return Unpooled.WrappedBuffer(outputStream.GetBuffer(), 0, (int)outputStream.Length);
56 | #endif
57 | }
58 | }
59 | finally
60 | {
61 | ReferenceCountUtil.Release(buffer);
62 | }
63 | }
64 | }
65 | }
--------------------------------------------------------------------------------
/host/ProtocolGateway.Host.Common/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | using System.Reflection;
5 | using System.Runtime.InteropServices;
6 |
7 | // General Information about an assembly is controlled through the following
8 | // set of attributes. Change these attribute values to modify the information
9 | // associated with an assembly.
10 |
11 | [assembly: AssemblyTitle("Microsoft.Azure.Devices.ProtocolGateway.Host.Common")]
12 | [assembly: AssemblyDescription("")]
13 | [assembly: AssemblyConfiguration("")]
14 | [assembly: AssemblyCompany("")]
15 | [assembly: AssemblyProduct("Microsoft.Azure.Devices.ProtocolGateway.Host.Common")]
16 | [assembly: AssemblyCopyright("Copyright © 2015")]
17 | [assembly: AssemblyTrademark("")]
18 | [assembly: AssemblyCulture("")]
19 |
20 | // Setting ComVisible to false makes the types in this assembly not visible
21 | // to COM components. If you need to access a type in this assembly from
22 | // COM, set the ComVisible attribute to true on that type.
23 |
24 | [assembly: ComVisible(false)]
25 |
26 | // The following GUID is for the ID of the typelib if this project is exposed to COM
27 |
28 | [assembly: Guid("6cc530d5-d1c6-4d14-88fb-b5b29d646cf8")]
29 |
30 | // Version information for an assembly consists of the following four values:
31 | //
32 | // Major Version
33 | // Minor Version
34 | // Build Number
35 | // Revision
36 | //
37 | // You can specify all the values or you can default the Build and Revision Numbers
38 | // by using the '*' as shown below:
39 | // [assembly: AssemblyVersion("1.0.*")]
40 |
41 | [assembly: AssemblyVersion("1.0.0.0")]
42 | [assembly: AssemblyFileVersion("1.0.0.0")]
--------------------------------------------------------------------------------
/host/ProtocolGateway.Host.Common/ProtocolGateway.Host.Common.NetStandard.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard1.3
5 | Microsoft.Azure.Devices.ProtocolGateway.Host.Common
6 | Microsoft.Azure.Devices.ProtocolGateway.Host.Common
7 | Library
8 | 1.6.1
9 | ProtocolGateway.Host.Common
10 | ProtocolGateway.Host.Common
11 | 1.0.0.0
12 | Copyright © Microsoft 2015
13 | Microsoft.Azure.Devices.ProtocolGateway.Host.Common
14 | Copyright © 2015
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/host/ProtocolGateway.Host.Common/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/host/ProtocolGateway.Host.Console.NetStandard/ConsoleEventListener.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace ProtocolGateway.Host.Console.NetStandard
5 | {
6 | using System.Diagnostics.Tracing;
7 | using System.Text;
8 |
9 | class ConsoleEventListener : EventListener
10 | {
11 | protected override void OnEventWritten(EventWrittenEventArgs eventData)
12 | {
13 | StringBuilder payload = new StringBuilder();
14 | foreach (object p in eventData.Payload)
15 | {
16 | payload.Append("[" + p + "]");
17 | }
18 | System.Console.WriteLine("EventId: {0}, Level: {1}, Message: {2}, Payload: {3} , EventName: {4}", eventData.EventId, eventData.Level, eventData.Message, payload.ToString(), eventData.EventName);
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/host/ProtocolGateway.Host.Console.NetStandard/Program.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace ProtocolGateway.Host.Console.NetStandard
5 | {
6 | using System;
7 | using System.Diagnostics.Tracing;
8 | using System.IO;
9 | using System.Security.Cryptography.X509Certificates;
10 | using System.Threading;
11 | using System.Threading.Tasks;
12 | using DotNetty.Common.Internal.Logging;
13 | using Microsoft.Azure.Devices.ProtocolGateway;
14 | using Microsoft.Azure.Devices.ProtocolGateway.Instrumentation;
15 | using Microsoft.Azure.Devices.ProtocolGateway.Mqtt.Persistence;
16 | using ProtocolGateway.Host.Common;
17 |
18 | class Program
19 | {
20 | static void Main(string[] args)
21 | {
22 | int threadCount = Environment.ProcessorCount;
23 | if (args.Length > 0)
24 | {
25 | threadCount = int.Parse(args[0]);
26 | }
27 |
28 | var eventListener = new ConsoleEventListener();
29 |
30 | eventListener.EnableEvents(BootstrapperEventSource.Log, EventLevel.Verbose);
31 | eventListener.EnableEvents(CommonEventSource.Log, EventLevel.Verbose);
32 | eventListener.EnableEvents(DefaultEventSource.Log, EventLevel.Verbose);
33 |
34 | try
35 | {
36 | var cts = new CancellationTokenSource();
37 |
38 | var certificate = new X509Certificate2(Path.Combine(AppContext.BaseDirectory, "protocol-gateway.contoso.com.pfx"), "password");
39 | var settingsProvider = new AppConfigSettingsProvider();
40 | ISessionStatePersistenceProvider sessionStateProvider = new TransientSessionStatePersistenceProvider();
41 |
42 | var bootstrapper = new Bootstrapper(settingsProvider, sessionStateProvider, null);
43 | Task.Run(() => bootstrapper.RunAsync(certificate, threadCount, cts.Token), cts.Token);
44 |
45 | while (true)
46 | {
47 | string input = Console.ReadLine();
48 | if (input != null && input.ToLowerInvariant() == "exit")
49 | {
50 | break;
51 | }
52 | }
53 |
54 | cts.Cancel();
55 | bootstrapper.CloseCompletion.Wait(TimeSpan.FromSeconds(20));
56 | }
57 | finally
58 | {
59 | eventListener.Dispose();
60 | }
61 | }
62 | }
63 | }
--------------------------------------------------------------------------------
/host/ProtocolGateway.Host.Console.NetStandard/ProtocolGateway.Host.Console.NetStandard.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | exe
5 | netcoreapp1.1
6 |
7 | exe
8 |
9 | ProtocolGateway.Host.Console
10 | ProtocolGateway.Host.Console
11 | 1.0.0.0
12 |
13 |
14 |
15 | bin\Debug
16 |
17 |
18 |
19 |
20 | PreserveNewest
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | PreserveNewest
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/host/ProtocolGateway.Host.Console.NetStandard/appSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "appSettings": {
3 | "MaxPendingInboundAcknowledgements": 16,
4 | "DeviceReceiveAckTimeout": "00:00:00",
5 | "MaxInboundMessageSize": "262144",
6 | "ConnectArrivalTimeout": "00:01:00",
7 | "MaxKeepAliveTimeout": "00:10:00",
8 | "RetainPropertyName": "mqtt-retain",
9 | "DupPropertyName": "mqtt-dup",
10 | "QoSPropertyName": "mqtt-qos",
11 | "IotHubClient.ConnectionString": "",
12 | "IotHubClient.MaxPendingInboundMessages": 10,
13 | "IotHubClient.MaxPendingOutboundMessages": 10,
14 | "IotHubClient.DefaultPublishToClientQoS": 1,
15 | "IotHubClient.MaxOutboundRetransmissionCount": 2,
16 | "IotHubClient.ConnectionPoolSize": 400,
17 | "IotHubClient.ConnectionIdleTimeout": "00:03:30",
18 | "BlobSessionStatePersistenceProvider.StorageConnectionString": "UseDevelopmentStorage=true",
19 | "BlobSessionStatePersistenceProvider.StorageContainerName": "mqtt-sessions",
20 | "TableQos2StatePersistenceProvider.StorageConnectionString": "UseDevelopmentStorage=true",
21 | "TableQos2StatePersistenceProvider.StorageTableName": "mqttqos2"
22 | },
23 | "mqttTopicNameConversion": {
24 | "InboundTemplates": [
25 | "devices/{deviceId}/messages/events/"
26 |
27 | ],
28 | "OutboundTemplates": [
29 | "devices/{deviceId}/messages/devicebound"
30 | ]
31 | }
32 | }
--------------------------------------------------------------------------------
/host/ProtocolGateway.Host.Console/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | using System.Reflection;
5 | using System.Resources;
6 |
7 | [assembly: NeutralResourcesLanguage("en-US")]
8 | [assembly: AssemblyMetadata("Serviceable", "True")]
--------------------------------------------------------------------------------
/host/ProtocolGateway.Host.Console/appSettings.config.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/host/ProtocolGateway.Host.Fabric.FrontEnd/PackageRoot/Code/InstallDotNet48.ps1:
--------------------------------------------------------------------------------
1 | #Requires -Version 3.0
2 |
3 | <#
4 | .DESCRIPTION
5 | Install .Net Framework 4.8
6 | #>
7 |
8 |
9 | [CmdletBinding()]
10 | Param(
11 | [switch]$norestart
12 | )
13 |
14 | Set-StrictMode -Version Latest
15 |
16 | $logFile = Join-Path $env:TEMP -ChildPath "InstallNetFx48ScriptLog.txt"
17 |
18 | # Check if the latest NetFx472 version exists
19 | $netFxKey = Get-ItemProperty -Path "HKLM:\SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v4\\Full\\" -ErrorAction Ignore
20 |
21 | if($netFxKey -and $netFxKey.Release -ge 528040) {
22 | "$(Get-Date): The machine already has NetFx 4.8 or later version installed." | Tee-Object -FilePath $logFile -Append
23 | exit 0
24 | }
25 |
26 | # Download the latest NetFx472
27 | $setupFileSourceUri = "https://download.visualstudio.microsoft.com/download/pr/7afca223-55d2-470a-8edc-6a1739ae3252/c9b8749dd99fc0d4453b2a3e4c37ba16/ndp48-web.exe"
28 | $setupFileLocalPath = Join-Path $env:TEMP -ChildPath "ndp48-web.exe"
29 |
30 | "$(Get-Date): Start to download NetFx 4.8 to $setupFileLocalPath." | Tee-Object -FilePath $logFile -Append
31 |
32 | if(Test-Path $setupFileLocalPath)
33 | {
34 | Remove-Item -Path $setupFileLocalPath -Force
35 | }
36 |
37 | $webClient = New-Object System.Net.WebClient
38 |
39 | $retry = 0
40 |
41 | do
42 | {
43 | try {
44 | $webClient.DownloadFile($setupFileSourceUri, $setupFileLocalPath)
45 | break
46 | }
47 | catch [Net.WebException] {
48 | $retry++
49 |
50 | if($retry -gt 3) {
51 | "$(Get-Date): Download failed as the network connection issue. Exception detail: $_" | Tee-Object -FilePath $logFile -Append
52 | break
53 | }
54 |
55 | $waitInSecond = $retry * 30
56 | "$(Get-Date): It looks the Internet network is not available now. Simply wait for $waitInSecond seconds and try again." | Tee-Object -FilePath $logFile -Append
57 | Start-Sleep -Second $waitInSecond
58 | }
59 | } while ($true)
60 |
61 |
62 | if(!(Test-Path $setupFileLocalPath))
63 | {
64 | "$(Get-Date): Failed to download NetFx 4.8 setup package." | Tee-Object -FilePath $logFile -Append
65 | exit -1
66 | }
67 |
68 | # Install NetFx48
69 | $setupLogFilePath = Join-Path $env:TEMP -ChildPath "NetFx48SetupLog.txt"
70 | if($norestart) {
71 | $arguments = "/q /norestart /serialdownload /log $setupLogFilePath"
72 | }
73 | else {
74 | $arguments = "/q /serialdownload /log $setupLogFilePath"
75 | }
76 | "$(Get-Date): Start to install NetFx 4.8" | Tee-Object -FilePath $logFile -Append
77 | $process = Start-Process -FilePath $setupFileLocalPath -ArgumentList $arguments -Wait -PassThru
78 |
79 | if(-not $process) {
80 | "$(Get-Date): Install NetFx failed." | Tee-Object -FilePath $logFile -Append
81 | exit -1
82 | }
83 | else {
84 | $exitCode = $process.ExitCode
85 |
86 | # 0, 1641 and 3010 indicate success. See https://msdn.microsoft.com/en-us/library/ee390831(v=vs.110).aspx for detail.
87 | if($exitCode -eq 0 -or $exitCode -eq 1641 -or $exitCode -eq 3010) {
88 | "$(Get-Date): Install NetFx succeeded with exit code : $exitCode." | Tee-Object -FilePath $logFile -Append
89 | exit 0
90 | }
91 | else {
92 | "$(Get-Date): Install NetFx failed with exit code : $exitCode." | Tee-Object -FilePath $logFile -Append
93 | exit -1
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/host/ProtocolGateway.Host.Fabric.FrontEnd/PackageRoot/Code/setup.cmd:
--------------------------------------------------------------------------------
1 | powershell.exe -ExecutionPolicy Bypass -Command ".\setup.ps1"
--------------------------------------------------------------------------------
/host/ProtocolGateway.Host.Fabric.FrontEnd/PackageRoot/Code/setup.ps1:
--------------------------------------------------------------------------------
1 | .\ProtocolGateway.Host.FabricSetup.CounterSetup.exe
2 |
3 | # Installing .NET Framework 4.8
4 | #.\InstallDotNet48.ps1 -norestart
5 |
6 | # Tweaking SChannel User Reference Context settings to prevent excessive contention on SChannel context lookup
7 | $listCount = 4096;
8 | $lockCount = 256;
9 | $props = Get-ItemProperty -Path Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\SecurityProviders\SCHANNEL;
10 | $oldListCount = $props.UserContextListCount;
11 | $oldLockCount = $props.UserContextLockCount;
12 | if ($oldListCount -ne $listCount -or $oldLockCount -ne $lockCount) {
13 | Write-Output "Updating SChannel settings. Old UserContextListCount: $oldListCount; old UserContextLockCount: $oldLockCount; New UserContextListCount: $listCount; new UserContextLockCount: $lockCount.";
14 | New-ItemProperty -Path Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\SecurityProviders\SCHANNEL -Name UserContextListCount -PropertyType "DWord" -Value $listCount -Force;
15 | New-ItemProperty -Path Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\SecurityProviders\SCHANNEL -Name UserContextLockCount -PropertyType "DWord" -Value $lockCount -Force;
16 | Restart-Computer;
17 | }
18 | else {
19 | Write-Output "SChannel settings are up to date"
20 | }
--------------------------------------------------------------------------------
/host/ProtocolGateway.Host.Fabric.FrontEnd/PackageRoot/Config/FrontEnd.AzureState.json:
--------------------------------------------------------------------------------
1 | {
2 | "BlobConnectionString": "UseDevelopmentStorage=true;",
3 | "ContainerName": "mqtt-sessions",
4 | "TableConnectionString": "UseDevelopmentStorage=true;",
5 | "TableName": "mqttqos2"
6 | }
--------------------------------------------------------------------------------
/host/ProtocolGateway.Host.Fabric.FrontEnd/PackageRoot/Config/FrontEnd.IoTHubClient.json:
--------------------------------------------------------------------------------
1 | {
2 | "ConnectionString": "TODO: IoT Hub connection string to connect to",
3 | "DefaultPublishToClientQoS": "1",
4 | "MaxPendingInboundMessages": "16",
5 | "MaxPendingOutboundMessages": "10",
6 | "MaxOutboundRetransmissionCount": "-1",
7 | "ConnectionPoolSize": "400",
8 | "ConnectionIdleTimeout": "00:03:30"
9 | }
10 |
--------------------------------------------------------------------------------
/host/ProtocolGateway.Host.Fabric.FrontEnd/PackageRoot/Config/FrontEnd.Mqtt.json:
--------------------------------------------------------------------------------
1 | {
2 | "RetainPropertyName": "mqtt-retain",
3 | "DupPropertyName": "mqtt-dup",
4 | "QoSPropertyName": "mqtt-qos",
5 | "MqttQoSStateProvider": "AzureStorage",
6 | "ConnectArrivalTimeout": "00:05:00",
7 | "MaxPendingInboundAcknowledgements": "16",
8 | "MaxInboundMessageSize": "262144",
9 | "MaxKeepAliveTimeout": "00:10:00"
10 | }
--------------------------------------------------------------------------------
/host/ProtocolGateway.Host.Fabric.FrontEnd/PackageRoot/Config/FrontEnd.json:
--------------------------------------------------------------------------------
1 | {
2 | "X509Identifier": "protocol-gateway.contoso.com.pfx",
3 | "X509Credential": "password",
4 | "X509Location": "Data",
5 | "EndPointName": "ServiceEndpoint",
6 | "HealthReportInterval": "00:00:15",
7 | "MetricsReportInterval": "00:00:15"
8 | }
--------------------------------------------------------------------------------
/host/ProtocolGateway.Host.Fabric.FrontEnd/PackageRoot/Config/Settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
--------------------------------------------------------------------------------
/host/ProtocolGateway.Host.Fabric.FrontEnd/PackageRoot/ServiceManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | setup.cmd
23 | CodePackage
24 |
25 |
26 |
27 |
28 | ProtocolGateway.Host.Fabric.FrontEnd.exe
29 |
30 |
31 |
32 |
34 |
35 |
36 |
37 |
38 |
39 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/host/ProtocolGateway.Host.Fabric.FrontEnd/Program.cs:
--------------------------------------------------------------------------------
1 | namespace ProtocolGateway.Host.Fabric.FrontEnd
2 | {
3 | #region Using Clauses
4 | using System;
5 | using System.Threading;
6 | using Microsoft.ServiceFabric.Services.Runtime;
7 | using FabricShared.Logging;
8 | using Logging;
9 | #endregion
10 |
11 | ///
12 | /// Host application to register service fabric types
13 | ///
14 | static class Program
15 | {
16 | ///
17 | /// This is the entry point of the service host process.
18 | ///
19 | static void Main()
20 | {
21 | const string SystemName = @"Protocol Gateway Front End";
22 | const string ComponentName = @"Registration Application";
23 |
24 | ILogger logger = new Logger(SystemName);
25 | Guid traceId = Guid.NewGuid();
26 |
27 | try
28 | {
29 | logger.Informational(traceId, ComponentName, "Initializing FrontEndType.");
30 | ServiceRuntime.RegisterServiceAsync("FrontEndType", context => new FrontEnd(traceId, SystemName, context)).GetAwaiter().GetResult();
31 | logger.Informational(traceId, ComponentName, "Services registered.");
32 |
33 | // Prevents this host process from terminating so services keep running.
34 | Thread.Sleep(Timeout.Infinite);
35 | }
36 | catch (Exception e)
37 | {
38 | logger.Critical(traceId, ComponentName, "Error during registration of type {0}.", new object[] { typeof(FrontEnd).Name }, e);
39 | throw;
40 | }
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/host/ProtocolGateway.Host.Fabric.FrontEnd/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("ProtocolGateway.Host.Fabric.FrontEnd")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("ProtocolGateway.Host.Fabric.FrontEnd")]
13 | [assembly: AssemblyCopyright("Copyright © 2016")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("a4701342-633a-4eee-ba50-7384156bebbd")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/host/ProtocolGateway.Host.Fabric.FrontEnd/configuration/AzureSessionStateConfiguration.cs:
--------------------------------------------------------------------------------
1 | namespace ProtocolGateway.Host.Fabric.FrontEnd.Configuration
2 | {
3 | ///
4 | /// Configuration details for the Azure storage provider
5 | ///
6 | public class AzureSessionStateConfiguration
7 | {
8 | ///
9 | /// Azure Storage connection string to be used by the BlobSessionStatePersistenceProvider to store MQTT session state data. Default value for
10 | /// Console sample and Cloud sample's Local configuration: UseDevelopmentStorage=true . For Cloud deployment the default value is a connection
11 | /// string to the specified storage account.
12 | ///
13 | public string BlobConnectionString { get; set; }
14 |
15 | ///
16 | /// Azure Storage Blob Container Name to be used by the BlobSessionStatePersistenceProvider to store MQTT session state data. Default value: mqtt-sessions
17 | ///
18 | public string ContainerName { get; set; }
19 |
20 | ///
21 | /// Azure Storage connection string to be used by TableQos2StatePersistenceProvider to store QoS 2 delivery information. Default value for Console sample and
22 | /// Cloud sample's Local configuration: UseDevelopmentStorage=true . For Cloud deployment the default value is a connection string to specified storage account.
23 | ///
24 | public string TableConnectionString { get; set; }
25 |
26 | ///
27 | /// Azure Storage Table name to be used by the TableQos2StatePersistenceProvider to store QoS 2 delivery information. Default value: mqttqos2
28 | ///
29 | public string TableName { get; set; }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/host/ProtocolGateway.Host.Fabric.FrontEnd/configuration/GatewayConfiguration.cs:
--------------------------------------------------------------------------------
1 | namespace ProtocolGateway.Host.Fabric.FrontEnd.Configuration
2 | {
3 | #region Using Clauses
4 | using System;
5 | #endregion
6 |
7 | ///
8 | /// Configuration information for the protocol gateway
9 | ///
10 | public sealed class GatewayConfiguration
11 | {
12 | ///
13 | /// The thumbprint of the certificate if in keyvault or local, file name if data store to use for server side MQTTS
14 | ///
15 | public string X509Identifier { get; set; }
16 |
17 |
18 | /// Todo: Secure this
19 |
20 | ///
21 | /// The file password, client credential for key vault for the server certificate
22 | ///
23 | public string X509Credential { get; set; }
24 |
25 | ///
26 | /// The location that the certificate is stored in
27 | ///
28 | public CertificateLocation X509Location { get; set; }
29 |
30 | ///
31 | /// The name of the endpoint in the endpoint list
32 | ///
33 | public string EndPointName { get; set; }
34 |
35 | ///
36 | /// The interval to report health at
37 | ///
38 | public TimeSpan HealthReportInterval { get; set; }
39 |
40 | ///
41 | /// The interval to report capacity metrics at
42 | ///
43 | public TimeSpan MetricsReportInterval { get; set; }
44 |
45 | ///
46 | /// The possible locations for the X509 certificate to be stored
47 | ///
48 | public enum CertificateLocation
49 | {
50 | LocalStore = 0,
51 | Data = 1,
52 | KeyVault = 2
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/host/ProtocolGateway.Host.Fabric.FrontEnd/configuration/IoTHubConfiguration.cs:
--------------------------------------------------------------------------------
1 | namespace ProtocolGateway.Host.Fabric.FrontEnd.Configuration
2 | {
3 | #region Using Clauses
4 | using System;
5 | #endregion
6 |
7 | ///
8 | /// IoTHubClient configuration data
9 | ///
10 | public class IoTHubConfiguration
11 | {
12 | ///
13 | /// REQUIRED Connection string to IoT hub. Defines the connection parameters when connecting to IoT hub on behalf of devices. By default,
14 | /// the protocol gateway will override the credentials from the connection string with the device credentials provided when a device connects
15 | /// to the gateway. No default value.
16 | ///
17 | public string ConnectionString { get; set; }
18 |
19 | ///
20 | /// Default Quality of Service to be used when publishing a message to a device. Can be overridden by adding a property on the message in
21 | /// IoT hub with the name defined by the QoSProperty setting and the value of the desired QoS level. Supported values are: 0, 1, 2.
22 | /// Default value: 1 (at least once)
23 | ///
24 | public int DefaultPublishToClientQoS { get; set; }
25 |
26 | ///
27 | /// Maximum allowed number of received messages pending processing. Protocol gateway will stop reading data from the device connection once
28 | /// it reaches MaxPendingInboundMessages and will restart only after the number of pending messages becomes lower than MaxPendingInboundMessages.
29 | /// Default value: 16
30 | ///
31 | public int MaxPendingInboundMessages { get; set; }
32 |
33 | ///
34 | /// Maximum allowed number of published device-bound messages pending acknowledgement. Protocol gateway will stop receiving messages from IoT hub
35 | /// once it reaches MaxPendingOutboundMessages and will restart only after the number of messages pending acknowledgement becomes lower than
36 | /// MaxPendingOutboundMessages. The number of messages is calculated as a sum of all unacknowledged messages: PUBLISH (QoS 1) pending PUBACK,
37 | /// PUBLISH (QoS 2) pending PUBREC, and PUBREL pending PUBCOMP. Default value: 1
38 | ///
39 | public int MaxPendingOutboundMessages { get; set; }
40 |
41 | ///
42 | /// If specified, maximum number of attempts to deliver a device-bound message. Messages that reach the limit of allowed delivery attempts will be
43 | /// rejected. If not specified or is less than or equal to 0, no maximum number of delivery attempts is imposed. Default value: -1
44 | ///
45 | public int MaxOutboundRetransmissionCount { get; set; }
46 |
47 | ///
48 | /// The maximum connection count to the IoT Hub
49 | ///
50 | public int ConnectionPoolSize { get; set; }
51 |
52 | ///
53 | /// The connection timeout for a client connected to the IoT Hub
54 | ///
55 | public TimeSpan ConnectionIdleTimeout { get; set; }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/host/ProtocolGateway.Host.Fabric.FrontEnd/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/host/ProtocolGateway.Host.Fabric/ApplicationPackageRoot/ApplicationManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/host/ProtocolGateway.Host.Fabric/ApplicationParameters/Cloud.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/host/ProtocolGateway.Host.Fabric/ApplicationParameters/Local.1Node.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/host/ProtocolGateway.Host.Fabric/ApplicationParameters/Local.5Node.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/host/ProtocolGateway.Host.Fabric/PublishProfiles/Cloud.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/host/ProtocolGateway.Host.Fabric/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/host/ProtocolGateway.Host.Fabric/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/host/Walkthrough.md:
--------------------------------------------------------------------------------
1 | # Samples Walkthrough
2 |
3 | Samples consist of the following projects:
4 |
5 | - **Gateway.Samples.Common** contains classes and resources used by both Cloud and Console samples. Here you can find bootstrapper and samples of additional handlers.
6 | - **Gateway.Samples.Console** showcases a console application host for Azure IoT Gateway.
7 | - **Gateway.Samples.Cloud.Host** serves as a host for cloud sample's entry point. It wires up the Bootstrapper to run in Azure Cloud Service.
8 | - **Gateway.Samples.Cloud** is a cloud project for packaging and deploying Gateway.Samples.Cloud.Host to Azure.
9 |
10 | ## Components
11 |
12 | ### Bootstrapper
13 |
14 | Bootstrapper showcases a configuration and lifecycle control for Azure IoT Gateway.
15 |
--------------------------------------------------------------------------------
/host/fabricsetup/ProtocolGateway.Host.FabricSetup.CounterSetup/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/host/fabricsetup/ProtocolGateway.Host.FabricSetup.CounterSetup/Program.cs:
--------------------------------------------------------------------------------
1 | namespace ProtocolGateway.Host.FabricSetup.CounterSetup
2 | {
3 | #region Using Clauses
4 | using System;
5 | using Microsoft.Azure.Devices.ProtocolGateway.Instrumentation;
6 | using logging;
7 | #endregion
8 |
9 | ///
10 | /// Used to register performance counters and the appropriate category for the service fabric front end service
11 | ///
12 | class Program
13 | {
14 | ///
15 | /// Primary entry point for the program
16 | ///
17 | ///
18 | static void Main(string[] args)
19 | {
20 | const string ComponentName = @"Front End Setup";
21 |
22 | var logger = new StartupLogger("Protocol Gateway Setup");
23 | Guid traceId = Guid.NewGuid();
24 |
25 | try
26 | {
27 | logger.Informational(traceId, ComponentName, "Launched.");
28 | PerformanceCounters.RegisterCountersIfRequired();
29 | logger.Informational(traceId, ComponentName, "Completed without exceptions.");
30 | }
31 | catch (Exception e)
32 | {
33 | logger.Critical(traceId, ComponentName, "Could not prepare the environment due to an error.", null, e);
34 | throw;
35 | }
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/host/fabricsetup/ProtocolGateway.Host.FabricSetup.CounterSetup/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("ProtocolGateway.Host.FabricSetup.CounterSetup")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("ProtocolGateway.Host.FabricSetup.CounterSetup")]
13 | [assembly: AssemblyCopyright("Copyright © 2016")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("07885ae0-1df1-4ba5-8197-f3514a06bdd3")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/host/fabricshared/ProtocolGateway.Host.Fabric.FabricShared.Configuration/ConfigurationChangedEventArgs.cs:
--------------------------------------------------------------------------------
1 | namespace ProtocolGateway.Host.Fabric.FabricShared.Configuration
2 | {
3 | #region Using Clauses
4 | using System;
5 | #endregion
6 |
7 | ///
8 | /// Configuration class changed event arguments.
9 | ///
10 | ///
11 | public sealed class ConfigurationChangedEventArgs : EventArgs where TConfiguration : class
12 | {
13 | #region Properties
14 | ///
15 | /// Name of the changed configuration.
16 | ///
17 | public string Name { get; }
18 |
19 | ///
20 | /// Configuration class instance.
21 | ///
22 | public TConfiguration CurrentConfiguration { get; }
23 |
24 | ///
25 | /// Configuration class instance.
26 | ///
27 | public TConfiguration NewConfiguration { get; }
28 |
29 | ///
30 | /// The name of the configuration
31 | ///
32 | public string ConfigurationName { get; }
33 | #endregion
34 | #region Constructors
35 | ///
36 | /// ConfigurationClassChangeEventArgs constructor.
37 | ///
38 | /// Name of the changed configuration.
39 | /// Current configuration instance of type TConfiguration.
40 | /// New configuration instance of type TConfiguration.
41 | /// The name of the configuration.
42 | public ConfigurationChangedEventArgs(string name, TConfiguration currentConfig, TConfiguration newConfig, string configurationName)
43 | {
44 | this.Name = name;
45 | this.CurrentConfiguration = currentConfig;
46 | this.NewConfiguration = newConfig;
47 | this.ConfigurationName = configurationName;
48 | }
49 | #endregion
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/host/fabricshared/ProtocolGateway.Host.Fabric.FabricShared.Configuration/IConfigurationProvider.cs:
--------------------------------------------------------------------------------
1 | namespace ProtocolGateway.Host.Fabric.FabricShared.Configuration
2 | {
3 | #region Using Clauses
4 | using System.Security;
5 | #endregion
6 |
7 | ///
8 | /// ConfigurationProvider interface.
9 | ///
10 | public interface IConfigurationProvider where TConfiguration : class
11 | {
12 | #region Properties
13 | ///
14 | /// Gets the configuration settings values.
15 | ///
16 | TConfiguration Config { get; }
17 |
18 | ///
19 | /// The name of the configuration to load. This will be appended to the name of the service when looking for the file (e.g. FrontEnd.Name.json)
20 | ///
21 | string ConfigurationName { get; }
22 | #endregion
23 | #region Methods
24 | ///
25 | /// Get a configuration value
26 | ///
27 | /// Name of the configuration item. Key value is case sensitive.
28 | /// Default value to return.
29 | /// Value of the configuration setting or the default value.
30 | string GetConfigurationString(string key, string defaultValue);
31 |
32 | ///
33 | /// Gets an encrypted configuration value.
34 | ///
35 | /// Name of the configuration item. Key value is case sensitive.
36 | /// Default value to return.
37 | /// Value of the configuration setting.
38 | SecureString GetEncryptedConfigurationString(string key, string defaultValue);
39 |
40 | ///
41 | /// Gets a configuration value of the specified type
42 | ///
43 | /// Name of the configuration item. Key value is case sensitive.
44 | /// Default value to return.
45 | /// Value of the configuration item or the default value.
46 | T GetConfigurationValue(string key, T defaultValue);
47 |
48 | ///
49 | /// Gets a configuration value of the specified type from a JSON string
50 | ///
51 | /// Name of the configuration item. Key value is case sensitive.
52 | /// Default value to return.
53 | /// Value of the configuration item or the default value.
54 | T GetConfigurationJsonValue(string key, T defaultValue);
55 | #endregion
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/host/fabricshared/ProtocolGateway.Host.Fabric.FabricShared.Configuration/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("ProtocolGateway.Host.Fabric.FabricShared.Configuration")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("ProtocolGateway.Host.Fabric.FabricShared.Configuration")]
13 | [assembly: AssemblyCopyright("Copyright © 2016")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("cedd1f60-e803-476a-9f73-3814cdce3c4b")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/host/fabricshared/ProtocolGateway.Host.Fabric.FabricShared.Configuration/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/host/fabricshared/ProtocolGateway.Host.Fabric.FabricShared.Configuration/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/host/fabricshared/ProtocolGateway.Host.Fabric.FabricShared.Health/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("ProtocolGateway.Host.Fabric.FabricShared.Health")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("ProtocolGateway.Host.Fabric.FabricShared.Health")]
13 | [assembly: AssemblyCopyright("Copyright © 2016")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("443e59d8-9395-41f1-aa8f-4895a734c2aa")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/host/fabricshared/ProtocolGateway.Host.Fabric.FabricShared.Health/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/host/fabricshared/ProtocolGateway.Host.Fabric.FabricShared.Logging/ExceptionExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace ProtocolGateway.Host.Fabric.FabricShared.Logging
2 | {
3 | #region Using Clauses
4 | using System;
5 | using System.Text;
6 | #endregion
7 |
8 | ///
9 | /// Extension class used for flattening exceptions
10 | ///
11 | public static class ExceptionExtensions
12 | {
13 | #region Public Methods
14 | ///
15 | /// Flattens the exceptions error message including all inner exceptions.
16 | ///
17 | /// The exception to flatten.
18 | /// A string representing the exceptions error message concatenated with the inner exception messages.
19 | public static string Flatten(this Exception exception)
20 | {
21 | string flatException = string.Empty;
22 |
23 | if (exception != null)
24 | {
25 | var aggregateException = exception as AggregateException;
26 |
27 | flatException = aggregateException == null ? FlattenException(exception) : FlattenAggregateException(aggregateException);
28 | }
29 |
30 | return flatException;
31 | }
32 | #endregion
33 | #region Private Methods
34 | ///
35 | /// Flattens a standard exception object.
36 | ///
37 | /// The exception to be flattened.
38 | /// A string that concatenates all inner exception messages as well.
39 | static string FlattenException(Exception exception)
40 | {
41 | var builder = new StringBuilder(exception.Message);
42 |
43 | if (exception.InnerException != null)
44 | {
45 | var aggregateException = exception.InnerException as AggregateException;
46 |
47 | builder.AppendLine(aggregateException == null
48 | ? FlattenException(exception.InnerException)
49 | : FlattenAggregateException(aggregateException));
50 | }
51 |
52 | return builder.ToString();
53 | }
54 |
55 | ///
56 | /// Flattens an aggregate exception object.
57 | ///
58 | /// An aggregate exception object to be flattened.
59 | /// A string that concatenates all inner exception messages as well.
60 | static string FlattenAggregateException(AggregateException exception)
61 | {
62 | var builder = new StringBuilder();
63 |
64 | if (exception.InnerExceptions != null)
65 | {
66 | builder.AppendLine(exception.Message);
67 |
68 | foreach (Exception innerException in exception.InnerExceptions)
69 | {
70 | var innerAggregateException = innerException as AggregateException;
71 |
72 | builder.AppendLine(innerAggregateException != null
73 | ? FlattenAggregateException(innerAggregateException)
74 | : FlattenException(innerException));
75 | }
76 | }
77 |
78 | return builder.ToString();
79 | }
80 | #endregion
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/host/fabricshared/ProtocolGateway.Host.Fabric.FabricShared.Logging/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("ProtocolGateway.Host.Fabric.FabricShared.Logging")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("ProtocolGateway.Host.Fabric.FabricShared.Logging")]
13 | [assembly: AssemblyCopyright("Copyright © 2016")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("a2537696-fd02-40cd-b179-2df85cc52a89")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/host/fabricshared/ProtocolGateway.Host.Fabric.FabricShared.Logging/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/host/fabricshared/ProtocolGateway.Host.Fabric.FabricShared.Security/CertificateUtilities.cs:
--------------------------------------------------------------------------------
1 | namespace ProtocolGateway.Host.Fabric.FabricShared.Security
2 | {
3 | #region Using Clauses
4 | using System;
5 | using System.Security;
6 | using System.Security.Cryptography.X509Certificates;
7 | #endregion
8 |
9 | ///
10 | /// Utilities associated with the X509 Certificates and their store
11 | ///
12 | public static class CertificateUtilities
13 | {
14 | #region Certificate Retrieval
15 | ///
16 | /// Retrieves an X509 Certificate from the specified store and location
17 | ///
18 | /// The certificate thumbprint
19 | /// The name of the store to retrieve the information from
20 | /// The location within the store where the certificate is located
21 | /// An X509 certificate with the specified thumbprint if available or null if not
22 | public static X509Certificate2 GetCertificate(string thumbprint, StoreName storeName, StoreLocation storeLocation)
23 | {
24 | X509Store store = null;
25 | X509Certificate2 certificate;
26 |
27 | try
28 | {
29 | store = new X509Store(storeName, storeLocation);
30 | store.Open(OpenFlags.ReadOnly);
31 | X509Certificate2Collection collection = store.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, false);
32 |
33 | certificate = collection.Count == 0 ? null : collection[0];
34 | }
35 | finally
36 | {
37 | store?.Close();
38 | }
39 |
40 | return certificate;
41 | }
42 |
43 | ///
44 | /// Retrieves an X509 certificate from a password protected PFX file file
45 | ///
46 | /// The X509 certificate
47 | public static X509Certificate2 GetCertificateFromFile(string fileName, SecureString password)
48 | {
49 | return new X509Certificate2(fileName, password);
50 | }
51 |
52 | ///
53 | /// Retrieves an X509 certificate from a password protected PFX file file
54 | ///
55 | /// The X509 certificate
56 | public static X509Certificate2 GetCertificateFromFile(string fileName, string password)
57 | {
58 | return new X509Certificate2(fileName, password);
59 | }
60 |
61 | ///
62 | /// Retrieves an X509 certificate from key vault
63 | ///
64 | /// The X509 certificate
65 | public static X509Certificate2 GetCertificateFromKeyVault(string fileName, SecureString password)
66 | {
67 | throw new NotImplementedException();
68 | }
69 | #endregion
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/host/fabricshared/ProtocolGateway.Host.Fabric.FabricShared.Security/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("ProtocolGateway.Host.Fabric.FabricShared.Security")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("ProtocolGateway.Host.Fabric.FabricShared.Security")]
13 | [assembly: AssemblyCopyright("Copyright © 2016")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("1cb06c3e-3d1c-4fd4-95e9-037b4361303a")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/host/fabricshared/ProtocolGateway.Host.Fabric.FabricShared.Security/ProtocolGateway.Host.Fabric.FabricShared.Security.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {1CB06C3E-3D1C-4FD4-95E9-037B4361303A}
8 | Library
9 | Properties
10 | ProtocolGateway.Host.Fabric.FabricShared.Security
11 | ProtocolGateway.Host.Fabric.FabricShared.Security
12 | v4.5.1
13 | 512
14 | true
15 |
16 |
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | pdbonly
27 | true
28 | bin\Release\
29 | TRACE
30 | prompt
31 | 4
32 |
33 |
34 | true
35 | bin\x64\Debug\
36 | DEBUG;TRACE
37 | full
38 | x64
39 | prompt
40 | MinimumRecommendedRules.ruleset
41 |
42 |
43 | bin\x64\Release\
44 | TRACE
45 | true
46 | pdbonly
47 | x64
48 | prompt
49 | MinimumRecommendedRules.ruleset
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
68 |
--------------------------------------------------------------------------------
/host/fabricshared/ProtocolGateway.Host.Fabric.FabricShared.Security/SecureStringExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace ProtocolGateway.Host.Fabric.FabricShared.Security
2 | {
3 | #region Using Clauses
4 | using System;
5 | using System.Runtime.InteropServices;
6 | using System.Security;
7 | #endregion
8 |
9 | ///
10 | /// Contains common secure string handling methods.
11 | ///
12 | public static class SecureStringExtensions
13 | {
14 | #region Extension Methods
15 | ///
16 | /// Creates a secure string based on the contents of the provided string.
17 | ///
18 | /// The string holding the contents of the secure string.
19 | /// A populated secure string that contains the value specified in the string parameter.
20 | public static SecureString GetSecureString(this string value)
21 | {
22 | var results = new SecureString();
23 |
24 | foreach (char character in value)
25 | {
26 | results.AppendChar(character);
27 | }
28 |
29 | return results;
30 | }
31 |
32 | ///
33 | /// Creates a CLR string based on the provided secure string value.
34 | ///
35 | /// The secure string that contains the value to be placed in the CLR string.
36 | ///
37 | public static string SecureStringToString(this SecureString value)
38 | {
39 | string plainValue = null;
40 |
41 | if (value != null)
42 | {
43 | IntPtr valuePtr = IntPtr.Zero;
44 |
45 | try
46 | {
47 | valuePtr = Marshal.SecureStringToGlobalAllocUnicode(value);
48 |
49 | plainValue = Marshal.PtrToStringUni(valuePtr);
50 | }
51 | finally
52 | {
53 | if (valuePtr != IntPtr.Zero) Marshal.ZeroFreeGlobalAllocUnicode(valuePtr);
54 | }
55 | }
56 |
57 | return plainValue;
58 | }
59 | #endregion
60 | }
61 | }
62 |
63 |
--------------------------------------------------------------------------------
/host/shared/protocol-gateway.contoso.com.pfx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Azure/azure-iot-protocol-gateway/4f6d32d1116a2cbc50fd608c8a5b44f5a1037971/host/shared/protocol-gateway.contoso.com.pfx
--------------------------------------------------------------------------------
/src/ProtocolGateway.Core/AppConfigSettingsProvider.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway
5 | {
6 | public class AppConfigSettingsProvider : ISettingsProvider
7 | {
8 | IAppConfigReader configStrategy;
9 |
10 | public AppConfigSettingsProvider()
11 | {
12 | #if NETSTANDARD1_3
13 | this.configStrategy = new ConfigurationExtensionReader();
14 | #else
15 | this.configStrategy = new ConfigManagerReader();
16 | #endif
17 | }
18 | public bool TryGetSetting(string name, out string value)
19 | {
20 | return configStrategy.TryGetSetting(name, out value);
21 | }
22 | }
23 | }
--------------------------------------------------------------------------------
/src/ProtocolGateway.Core/ConfigManagerReader.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway
5 | {
6 | using System.Configuration;
7 |
8 | class ConfigManagerReader : IAppConfigReader
9 | {
10 | public bool TryGetSetting(string name, out string value)
11 | {
12 | string[] values = ConfigurationManager.AppSettings.GetValues(name);
13 | if (values == null || values.Length == 0)
14 | {
15 | value = default(string);
16 | return false;
17 | }
18 |
19 | value = values[0];
20 | return true;
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/ProtocolGateway.Core/ConfigurationErrorsException.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway
5 | {
6 | using System;
7 |
8 | public class ConfigurationErrorsException : Exception
9 | {
10 | public ConfigurationErrorsException()
11 | {
12 | }
13 |
14 | public ConfigurationErrorsException(string message) : base(message)
15 | {
16 | }
17 |
18 | public ConfigurationErrorsException(string message, Exception innerException) : base(message, innerException)
19 | {
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------
/src/ProtocolGateway.Core/ConfigurationExtensionReader.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway
5 | {
6 | using Microsoft.Extensions.Configuration;
7 |
8 | public class ConfigurationExtensionReader : IAppConfigReader
9 | {
10 | static readonly IConfiguration Config = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build();
11 |
12 | public bool TryGetSetting(string name, out string value)
13 | {
14 | IConfigurationSection appsettings = Config.GetSection("AppSettings");
15 | value = appsettings.GetSection(name).Value;
16 | if (value == null)
17 | {
18 | value = default(string);
19 | return false;
20 | }
21 |
22 | return true;
23 | }
24 | }
25 | }
--------------------------------------------------------------------------------
/src/ProtocolGateway.Core/ErrorCode.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway
5 | {
6 | public enum ErrorCode
7 | {
8 | InvalidErrorCode = 0,
9 |
10 | //BadRequest - 400
11 | InvalidPubAckOrder = 400001,
12 | GenericTimeOut = 400002,
13 | InvalidOperation = 400003,
14 | NotSupported = 400004,
15 | KeepAliveTimedOut = 400005,
16 | ConnectionTimedOut = 400006,
17 | ConnectExpected = 400007,
18 | UnResolvedSendingClient = 400008,
19 | UnknownQosType = 400009,
20 | QoSLevelNotSupported = 400010,
21 | ExactlyOnceQosNotSupported = 400011,
22 | UnknownPacketType = 400012,
23 | DuplicateConnectReceived = 400013,
24 |
25 | AuthenticationFailed = 401000,
26 |
27 | //ClientClosedRequest - 499
28 | ChannelClosed = 499001,
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/ProtocolGateway.Core/Extensions/TaskExtensions.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Extensions
5 | {
6 | using System;
7 | using System.Threading.Tasks;
8 |
9 | public static class TaskExtensions
10 | {
11 | public static void OnFault(this Task task, Action faultAction)
12 | {
13 | switch (task.Status)
14 | {
15 | case TaskStatus.RanToCompletion:
16 | case TaskStatus.Canceled:
17 | break;
18 | case TaskStatus.Faulted:
19 | faultAction(task);
20 | break;
21 | default:
22 | task.ContinueWith(faultAction, TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.ExecuteSynchronously);
23 | break;
24 | }
25 | }
26 |
27 | public static void OnFault(this Task task, Action faultAction, object state)
28 | {
29 | switch (task.Status)
30 | {
31 | case TaskStatus.RanToCompletion:
32 | case TaskStatus.Canceled:
33 | break;
34 | case TaskStatus.Faulted:
35 | faultAction(task, state);
36 | break;
37 | default:
38 | task.ContinueWith(faultAction, state, TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.ExecuteSynchronously);
39 | break;
40 | }
41 | }
42 | }
43 | }
--------------------------------------------------------------------------------
/src/ProtocolGateway.Core/IAppConfigReader.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway
5 | {
6 | using System;
7 | using System.Collections.Generic;
8 | using System.Linq;
9 | using System.Text;
10 | using System.Threading.Tasks;
11 |
12 | interface IAppConfigReader
13 | {
14 | bool TryGetSetting(string name, out string value);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/ProtocolGateway.Core/Identity/IDeviceIdentity.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Identity
5 | {
6 | public interface IDeviceIdentity
7 | {
8 | bool IsAuthenticated { get; }
9 |
10 | string Id { get; }
11 | }
12 | }
--------------------------------------------------------------------------------
/src/ProtocolGateway.Core/Identity/IDeviceIdentityProvider.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Identity
5 | {
6 | using System.Net;
7 | using System.Threading.Tasks;
8 |
9 | public interface IDeviceIdentityProvider
10 | {
11 | Task GetAsync(string clientId, string username, string password, EndPoint clientAddress);
12 | }
13 | }
--------------------------------------------------------------------------------
/src/ProtocolGateway.Core/Identity/UnauthenticatedDeviceIdentity.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Identity
5 | {
6 | using System;
7 |
8 | public sealed class UnauthenticatedDeviceIdentity : IDeviceIdentity
9 | {
10 | public static IDeviceIdentity Instance { get; } = new UnauthenticatedDeviceIdentity();
11 |
12 | UnauthenticatedDeviceIdentity()
13 | {
14 | }
15 |
16 | public bool IsAuthenticated => false;
17 |
18 | public string Id
19 | {
20 | get { throw new InvalidOperationException("Accessing identity of device while authentication failed."); }
21 | }
22 | }
23 | }
--------------------------------------------------------------------------------
/src/ProtocolGateway.Core/Instrumentation/AveragePerformanceCounter.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Instrumentation
5 | {
6 | using DotNetty.Common;
7 |
8 | public sealed class AveragePerformanceCounter
9 | {
10 | readonly IPerformanceCounter countCounter;
11 | readonly IPerformanceCounter baseCounter;
12 |
13 | public AveragePerformanceCounter(IPerformanceCounter countCounter, IPerformanceCounter baseCounter)
14 | {
15 | this.countCounter = countCounter;
16 | this.baseCounter = baseCounter;
17 | }
18 |
19 | public void Register(PreciseTimeSpan startTimestamp)
20 | {
21 | PreciseTimeSpan elapsed = PreciseTimeSpan.FromStart - startTimestamp;
22 | long elapsedMs = (long)elapsed.ToTimeSpan().TotalMilliseconds;
23 | this.countCounter.IncrementBy(elapsedMs);
24 | this.baseCounter.Increment();
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/src/ProtocolGateway.Core/Instrumentation/CommonEventSource.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Instrumentation
5 | {
6 | using System;
7 | using System.Diagnostics.Tracing;
8 |
9 | [EventSource(
10 | Name = "IoT-ProtocolGateway-Common",
11 | Guid = "06d7118e-3a71-4143-8aab-ed8cedf69e1c")]
12 | public class CommonEventSource : EventSource
13 | {
14 | const int VerboseEventId = 1;
15 | const int InfoEventId = 2;
16 | const int WarningEventId = 3;
17 | const int ErrorEventId = 4;
18 |
19 | public static readonly CommonEventSource Log = new CommonEventSource();
20 |
21 | CommonEventSource()
22 | {
23 | }
24 |
25 | public bool IsVerboseEnabled => this.IsEnabled(EventLevel.Verbose, EventKeywords.None);
26 |
27 | public bool IsInfoEnabled => this.IsEnabled(EventLevel.Informational, EventKeywords.None);
28 |
29 | public bool IsWarningEnabled => this.IsEnabled(EventLevel.Warning, EventKeywords.None);
30 |
31 | public bool IsErrorEnabled => this.IsEnabled(EventLevel.Error, EventKeywords.None);
32 |
33 | [NonEvent]
34 | public void Verbose(string message) => this.Verbose(message, string.Empty, string.Empty);
35 |
36 | [Event(VerboseEventId, Level = EventLevel.Verbose)]
37 | public void Verbose(string message, string channelId, string deviceId) => this.WriteEvent(VerboseEventId, message, channelId, deviceId);
38 |
39 | [Event(InfoEventId, Level = EventLevel.Informational)]
40 | public void Info(string message, string channelId, string deviceId) => this.WriteEvent(InfoEventId, message, channelId, deviceId);
41 |
42 | [NonEvent]
43 | public void Warning(string message, string channelId, string deviceId) => this.Warning(message, string.Empty, channelId, deviceId);
44 |
45 | [NonEvent]
46 | public void Warning(string message, Exception exception, string channelId, string deviceId) => this.Warning(message, exception?.ToString() ?? string.Empty, channelId, deviceId);
47 |
48 | [Event(WarningEventId, Level = EventLevel.Warning)]
49 | public void Warning(string message, string exception, string channelId, string deviceId) => this.WriteEvent(WarningEventId, message, exception, channelId, deviceId);
50 |
51 | [NonEvent]
52 | public void Error(string message, Exception exception, string channelId, string deviceId) => this.Error(message, exception?.ToString() ?? string.Empty, channelId, deviceId);
53 |
54 | [Event(ErrorEventId, Level = EventLevel.Error)]
55 | public void Error(string message, string exception, string channelId, string deviceId) => this.WriteEvent(ErrorEventId, message, exception, channelId, deviceId);
56 | }
57 | }
--------------------------------------------------------------------------------
/src/ProtocolGateway.Core/Instrumentation/EmptyPerformanceCounter.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Instrumentation
5 | {
6 | public sealed class EmptyPerformanceCounter : IPerformanceCounter
7 | {
8 | public long RawValue { get; set; }
9 | public string CounterName { get; private set; }
10 |
11 | public EmptyPerformanceCounter(string name)
12 | {
13 | this.CounterName = name;
14 | }
15 |
16 | public EmptyPerformanceCounter()
17 | {
18 | }
19 |
20 | public float NextValue
21 | {
22 | get { return 0; }
23 | }
24 |
25 | public void Increment()
26 | {
27 | }
28 |
29 | public void IncrementBy(long value)
30 | {
31 | }
32 |
33 | public void Decrement()
34 | {
35 | }
36 | }
37 | }
--------------------------------------------------------------------------------
/src/ProtocolGateway.Core/Instrumentation/EmptyPerformanceCounterManager.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Instrumentation
5 | {
6 | public class EmptyPerformanceCounterManager : IPerformanceCounterManager
7 | {
8 | public IPerformanceCounter GetCounter(string category, string name)
9 | {
10 | return new EmptyPerformanceCounter();
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/ProtocolGateway.Core/Instrumentation/IPerformanceCounter.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Instrumentation
5 | {
6 | public interface IPerformanceCounter
7 | {
8 | long RawValue { get; set; }
9 | float NextValue { get; }
10 | void Increment();
11 | void IncrementBy(long value);
12 | void Decrement();
13 | }
14 | }
--------------------------------------------------------------------------------
/src/ProtocolGateway.Core/Instrumentation/IPerformanceCounterManager.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Instrumentation
5 | {
6 | public interface IPerformanceCounterManager
7 | {
8 | IPerformanceCounter GetCounter(string category, string name);
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/ProtocolGateway.Core/Instrumentation/PerformanceCounterCategoryInfo.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Instrumentation
5 | {
6 | using System.Diagnostics;
7 |
8 | public sealed class PerformanceCounterCategoryInfo
9 | {
10 | public PerformanceCounterCategoryInfo(string categoryName, PerformanceCounterCategoryType categoryType, string categoryHelp)
11 | {
12 | this.CategoryName = categoryName;
13 | this.CategoryType = categoryType;
14 | this.CategoryHelp = categoryHelp;
15 | }
16 |
17 | public string CategoryName { get; private set; }
18 |
19 | public PerformanceCounterCategoryType CategoryType { get; private set; }
20 |
21 | public string CategoryHelp { get; private set; }
22 | }
23 | }
--------------------------------------------------------------------------------
/src/ProtocolGateway.Core/Instrumentation/SafePerformanceCounter.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Instrumentation
5 | {
6 | using System;
7 | using System.Diagnostics;
8 |
9 | public sealed class SafePerformanceCounter : IPerformanceCounter
10 | {
11 | readonly PerformanceCounter counter;
12 |
13 | public SafePerformanceCounter(PerformanceCounter counter)
14 | {
15 | this.counter = counter;
16 | }
17 |
18 | public long RawValue
19 | {
20 | get { return this.counter.RawValue; }
21 | set { this.counter.RawValue = value; }
22 | }
23 |
24 | public float NextValue
25 | {
26 | get
27 | {
28 | return this.counter.NextValue();
29 | }
30 | }
31 |
32 | public void Increment()
33 | {
34 | try
35 | {
36 | this.counter.Increment();
37 | }
38 | catch (Exception ex)
39 | {
40 | CommonEventSource.Log.Verbose("Failed to increment perf counter: " + ex.ToString());
41 | }
42 | }
43 |
44 | public void IncrementBy(long value)
45 | {
46 | try
47 | {
48 | this.counter.IncrementBy(value);
49 | }
50 | catch (Exception ex)
51 | {
52 | CommonEventSource.Log.Verbose("Failed to increment perf counter: " + ex.ToString());
53 | }
54 | }
55 |
56 | public void Decrement()
57 | {
58 | try
59 | {
60 | this.counter.Decrement();
61 | }
62 | catch (Exception ex)
63 | {
64 | CommonEventSource.Log.Verbose("Failed to decrement perf counter: " + ex.ToString());
65 | }
66 | }
67 | }
68 | }
--------------------------------------------------------------------------------
/src/ProtocolGateway.Core/Messaging/IBatchAwareMessagingServiceClient.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Messaging
5 | {
6 | using System.Collections.Generic;
7 | using System.Threading.Tasks;
8 |
9 | public interface IBatchAwareMessagingServiceClient : IMessagingServiceClient
10 | {
11 | Task SendBatchAsync(IReadOnlyCollection messages);
12 |
13 | int MaxBatchSize { get; }
14 | }
15 | }
--------------------------------------------------------------------------------
/src/ProtocolGateway.Core/Messaging/IMessage.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Messaging
5 | {
6 | using System;
7 | using System.Collections.Generic;
8 | using DotNetty.Buffers;
9 |
10 | public interface IMessage : IDisposable
11 | {
12 | string Address { get; }
13 |
14 | IByteBuffer Payload { get; }
15 |
16 | string Id { get; }
17 |
18 | IDictionary Properties { get; }
19 |
20 | DateTime CreatedTimeUtc { get; }
21 |
22 | uint DeliveryCount { get; }
23 |
24 | ulong SequenceNumber { get; }
25 | }
26 | }
--------------------------------------------------------------------------------
/src/ProtocolGateway.Core/Messaging/IMessagingBridge.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Messaging
5 | {
6 | using System;
7 | using System.Threading.Tasks;
8 |
9 | public interface IMessagingBridge
10 | {
11 | void BindMessagingChannel(IMessagingChannel channel);
12 |
13 | bool TryResolveClient(string topicName, out IMessagingServiceClient sendingClient);
14 |
15 | Task DisposeAsync(Exception cause);
16 | }
17 | }
--------------------------------------------------------------------------------
/src/ProtocolGateway.Core/Messaging/IMessagingChannel.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Messaging
5 | {
6 | using System;
7 |
8 | public interface IMessagingChannel
9 | {
10 | void Handle(IMessage message, IMessagingSource sender);
11 |
12 | void Close(Exception cause);
13 |
14 | event EventHandler CapabilitiesChanged;
15 | }
16 | }
--------------------------------------------------------------------------------
/src/ProtocolGateway.Core/Messaging/IMessagingServiceClient.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Messaging
5 | {
6 | using System;
7 | using System.Threading.Tasks;
8 | using DotNetty.Buffers;
9 |
10 | public interface IMessagingServiceClient
11 | {
12 | int MaxPendingMessages { get; }
13 |
14 | IMessage CreateMessage(string address, IByteBuffer payload);
15 |
16 | Task SendAsync(IMessage message);
17 |
18 | Task DisposeAsync(Exception cause);
19 | }
20 | }
--------------------------------------------------------------------------------
/src/ProtocolGateway.Core/Messaging/IMessagingSource.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Messaging
5 | {
6 | using System;
7 | using System.Threading.Tasks;
8 |
9 | public interface IMessagingSource
10 | {
11 | void BindMessagingChannel(IMessagingChannel channel);
12 |
13 | Task CompleteAsync(string messageId);
14 |
15 | Task RejectAsync(string messageId);
16 |
17 | Task DisposeAsync(Exception cause);
18 | }
19 | }
--------------------------------------------------------------------------------
/src/ProtocolGateway.Core/Messaging/Message.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Messaging
5 | {
6 | using System;
7 | using System.Collections.Generic;
8 | using DotNetty.Buffers;
9 | using DotNetty.Common.Utilities;
10 |
11 | public sealed class Message : IMessage
12 | {
13 | Dictionary properties;
14 |
15 | public string Address { get; set; }
16 |
17 | public IByteBuffer Payload { get; set; }
18 |
19 | public string Id { get; set; }
20 |
21 | public IDictionary Properties => this.properties ?? (this.properties = new Dictionary(3));
22 |
23 | public DateTime CreatedTimeUtc { get; set; }
24 |
25 | public uint DeliveryCount { get; set; }
26 |
27 | public ulong SequenceNumber { get; set; }
28 |
29 | public void Dispose()
30 | {
31 | if (this.Payload != null)
32 | {
33 | ReferenceCountUtil.SafeRelease(this.Payload);
34 | }
35 | }
36 | }
37 | }
--------------------------------------------------------------------------------
/src/ProtocolGateway.Core/Messaging/MessagingException.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 | namespace Microsoft.Azure.Devices.ProtocolGateway.Messaging
4 | {
5 | using System;
6 |
7 | public class MessagingException: Exception
8 | {
9 |
10 | public bool IsTransient { get; }
11 |
12 | public string TrackingId { get; set; }
13 |
14 | public MessagingException(string message)
15 | : this(message, false)
16 | {
17 | }
18 |
19 | public MessagingException(string message, bool isTransient)
20 | : this(message, isTransient, string.Empty)
21 | {
22 | }
23 |
24 | public MessagingException(string message, string trackingId)
25 | : this(message, false, trackingId)
26 | {
27 | }
28 |
29 | public MessagingException(string message, bool isTransient, string trackingId)
30 | : base(message)
31 | {
32 | this.IsTransient = isTransient;
33 | this.TrackingId = trackingId;
34 | }
35 |
36 | public MessagingException(string message, Exception innerException)
37 | : this(message, innerException, false)
38 | {
39 | }
40 |
41 | public MessagingException(string message, Exception innerException, bool isTransient)
42 | : this(message, innerException, isTransient, string.Empty)
43 | {
44 | }
45 |
46 | public MessagingException(string message, Exception innerException, string trackingId)
47 | : this(message, innerException, false, trackingId)
48 | {
49 | }
50 |
51 | public MessagingException(string message, Exception innerException, bool isTransient, string trackingId)
52 | : base(message, innerException)
53 | {
54 | this.IsTransient = isTransient;
55 | this.TrackingId = trackingId;
56 | }
57 | }
58 | }
--------------------------------------------------------------------------------
/src/ProtocolGateway.Core/Mqtt/AckPendingMessageState.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Mqtt
5 | {
6 | using DotNetty.Codecs.Mqtt.Packets;
7 | using DotNetty.Common;
8 | using Microsoft.Azure.Devices.ProtocolGateway.Messaging;
9 |
10 | sealed class AckPendingMessageState : IPacketReference // todo: recycle?
11 | {
12 | public AckPendingMessageState(IMessage message, IMessagingSource callback, PublishPacket packet)
13 | {
14 | this.SequenceNumber = message.SequenceNumber;
15 | this.PacketId = packet.PacketId;
16 | this.QualityOfService = packet.QualityOfService;
17 | this.FeedbackChannel = new MessageFeedbackChannel(message.Id, callback);
18 | this.StartTimestamp = PreciseTimeSpan.FromStart;
19 | }
20 |
21 | public PreciseTimeSpan StartTimestamp { get; set; }
22 |
23 | public ulong SequenceNumber { get; }
24 |
25 | public int PacketId { get; }
26 |
27 | public QualityOfService QualityOfService { get; private set; }
28 |
29 | public MessageFeedbackChannel FeedbackChannel { get; private set; }
30 | }
31 | }
--------------------------------------------------------------------------------
/src/ProtocolGateway.Core/Mqtt/ChannelMessageProcessingException.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Mqtt
5 | {
6 | using System;
7 | using DotNetty.Transport.Channels;
8 |
9 | public class ChannelMessageProcessingException : Exception
10 | {
11 | public ChannelMessageProcessingException(Exception innerException, IChannelHandlerContext context)
12 | : base(string.Empty, innerException)
13 | {
14 | this.Context = context;
15 | }
16 |
17 | public IChannelHandlerContext Context { get; private set; }
18 | }
19 | }
--------------------------------------------------------------------------------
/src/ProtocolGateway.Core/Mqtt/CompletionPendingMessageState.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Mqtt
5 | {
6 | using DotNetty.Common;
7 | using Microsoft.Azure.Devices.ProtocolGateway.Messaging;
8 | using Microsoft.Azure.Devices.ProtocolGateway.Mqtt.Persistence;
9 |
10 | sealed class CompletionPendingMessageState : IPacketReference
11 | {
12 | public CompletionPendingMessageState(int packetId, IQos2MessageDeliveryState deliveryState,
13 | PreciseTimeSpan startTimestamp, MessageFeedbackChannel feedbackChannel)
14 | {
15 | this.PacketId = packetId;
16 | this.DeliveryState = deliveryState;
17 | this.StartTimestamp = startTimestamp;
18 | this.FeedbackChannel = feedbackChannel;
19 | }
20 |
21 | public int PacketId { get; }
22 |
23 | public IQos2MessageDeliveryState DeliveryState { get; private set; }
24 |
25 | public PreciseTimeSpan StartTimestamp { get; private set; }
26 |
27 | public MessageFeedbackChannel FeedbackChannel { get; set; }
28 | }
29 | }
--------------------------------------------------------------------------------
/src/ProtocolGateway.Core/Mqtt/IMessageProcessor.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Mqtt
5 | {
6 | using System.Threading.Tasks;
7 | using DotNetty.Transport.Channels;
8 |
9 | public interface IMessageProcessor
10 | {
11 | void Post(IChannelHandlerContext context, T message);
12 |
13 | int BacklogSize { get; }
14 |
15 | Task Closed { get; }
16 |
17 | void Close();
18 | }
19 | }
--------------------------------------------------------------------------------
/src/ProtocolGateway.Core/Mqtt/IPacketReference.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Mqtt
5 | {
6 | interface IPacketReference
7 | {
8 | int PacketId { get; }
9 | }
10 | }
--------------------------------------------------------------------------------
/src/ProtocolGateway.Core/Mqtt/MessageAsyncProcessor.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Mqtt
5 | {
6 | using System;
7 | using System.Threading.Tasks;
8 | using DotNetty.Transport.Channels;
9 |
10 | public sealed class MessageAsyncProcessor : MessageAsyncProcessorBase, IMessageProcessor
11 | {
12 | readonly Func processFunc;
13 |
14 | public MessageAsyncProcessor(Func processFunc)
15 | {
16 | this.processFunc = processFunc;
17 | }
18 |
19 | protected override Task ProcessAsync(IChannelHandlerContext context, T packet) => this.processFunc(context, packet);
20 | }
21 | }
--------------------------------------------------------------------------------
/src/ProtocolGateway.Core/Mqtt/MessageFeedbackChannel.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Messaging
5 | {
6 | using System.Threading.Tasks;
7 |
8 | public struct MessageFeedbackChannel
9 | {
10 | readonly string messageId;
11 | readonly IMessagingSource callback;
12 |
13 | public MessageFeedbackChannel(string messageId, IMessagingSource callback)
14 | {
15 | this.messageId = messageId;
16 | this.callback = callback;
17 | }
18 |
19 | public Task CompleteAsync() => this.callback.CompleteAsync(this.messageId);
20 |
21 | public Task RejectAsync() => this.callback.RejectAsync(this.messageId);
22 | }
23 | }
--------------------------------------------------------------------------------
/src/ProtocolGateway.Core/Mqtt/MessagePropertyNames.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Mqtt
5 | {
6 | public static class MessagePropertyNames
7 | {
8 | public const string MessageType = "MessageType";
9 | public const string Unmatched = "Unmatched";
10 | public const string Subject = "Subject";
11 |
12 | }
13 | }
--------------------------------------------------------------------------------
/src/ProtocolGateway.Core/Mqtt/MessageTypes.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Mqtt
5 | {
6 | public static class MessageTypes
7 | {
8 | public const string Will = "Will";
9 | }
10 | }
--------------------------------------------------------------------------------
/src/ProtocolGateway.Core/Mqtt/MessagingBridgeFactoryFunc.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Mqtt
5 | {
6 | using System.Threading;
7 | using System.Threading.Tasks;
8 | using Microsoft.Azure.Devices.ProtocolGateway.Identity;
9 | using Microsoft.Azure.Devices.ProtocolGateway.Messaging;
10 |
11 | public delegate Task MessagingBridgeFactoryFunc(IDeviceIdentity deviceIdentity, CancellationToken cancellationToken);
12 | }
--------------------------------------------------------------------------------
/src/ProtocolGateway.Core/Mqtt/Persistence/IQoS2MessageDeliveryState.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Mqtt.Persistence
5 | {
6 | using System;
7 |
8 | public interface IQos2MessageDeliveryState
9 | {
10 | DateTime LastModified { get; }
11 |
12 | ulong SequenceNumber { get; }
13 | }
14 | }
--------------------------------------------------------------------------------
/src/ProtocolGateway.Core/Mqtt/Persistence/IQos2StatePersistenceProvider.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Mqtt.Persistence
5 | {
6 | using System.Threading.Tasks;
7 | using Microsoft.Azure.Devices.ProtocolGateway.Identity;
8 |
9 | public interface IQos2StatePersistenceProvider
10 | {
11 | IQos2MessageDeliveryState Create(ulong sequenceNumber);
12 |
13 | ///
14 | /// Performs a lookup of message delivery state by packet identifier
15 | ///
16 | /// Device identity
17 | /// Packet identifier
18 | ///
19 | /// object if message was previously persisted with
20 | /// the given packet id; null - if no message could be found.
21 | ///
22 | Task GetMessageAsync(IDeviceIdentity deviceIdentity, int packetId);
23 |
24 | Task DeleteMessageAsync(IDeviceIdentity deviceIdentity, int packetId, IQos2MessageDeliveryState message);
25 |
26 | Task SetMessageAsync(IDeviceIdentity deviceIdentity, int packetId, IQos2MessageDeliveryState message);
27 | }
28 | }
--------------------------------------------------------------------------------
/src/ProtocolGateway.Core/Mqtt/Persistence/ISessionState.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Mqtt.Persistence
5 | {
6 | using System.Collections.Generic;
7 | using DotNetty.Codecs.Mqtt.Packets;
8 |
9 | public interface ISessionState
10 | {
11 | IReadOnlyList Subscriptions { get; }
12 |
13 | bool IsTransient { get; }
14 |
15 | ISessionState Copy();
16 |
17 | bool AddOrUpdateSubscription(string topicFilter, QualityOfService qos);
18 |
19 | bool RemoveSubscription(string topicFilter);
20 | }
21 | }
--------------------------------------------------------------------------------
/src/ProtocolGateway.Core/Mqtt/Persistence/ISessionStatePersistenceProvider.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Mqtt.Persistence
5 | {
6 | using System.Threading.Tasks;
7 | using Microsoft.Azure.Devices.ProtocolGateway.Identity;
8 |
9 | public interface ISessionStatePersistenceProvider
10 | {
11 | ISessionState Create(bool transient);
12 |
13 | Task GetAsync(IDeviceIdentity identity);
14 |
15 | Task SetAsync(IDeviceIdentity identity, ISessionState sessionState);
16 |
17 | Task DeleteAsync(IDeviceIdentity identity, ISessionState sessionState);
18 | }
19 | }
--------------------------------------------------------------------------------
/src/ProtocolGateway.Core/Mqtt/Persistence/ISubscription.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Mqtt.Persistence
5 | {
6 | using System;
7 | using DotNetty.Codecs.Mqtt.Packets;
8 |
9 | public interface ISubscription
10 | {
11 | DateTime CreationTime { get; }
12 |
13 | string TopicFilter { get; }
14 |
15 | QualityOfService QualityOfService { get; }
16 |
17 | ISubscription CreateUpdated(QualityOfService qos);
18 | }
19 | }
--------------------------------------------------------------------------------
/src/ProtocolGateway.Core/Mqtt/Persistence/TransientSessionState.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Mqtt.Persistence
5 | {
6 | using System;
7 | using System.Collections.Generic;
8 | using DotNetty.Codecs.Mqtt.Packets;
9 |
10 | class TransientSessionState : ISessionState
11 | {
12 | readonly List subscriptions;
13 |
14 | public TransientSessionState(bool transient)
15 | {
16 | this.IsTransient = transient;
17 | this.subscriptions = new List();
18 | }
19 |
20 | public bool IsTransient { get; }
21 |
22 | public IReadOnlyList Subscriptions => this.subscriptions;
23 |
24 | public ISessionState Copy()
25 | {
26 | var sessionState = new TransientSessionState(this.IsTransient);
27 | sessionState.subscriptions.AddRange(this.Subscriptions);
28 | return sessionState;
29 | }
30 |
31 | public bool RemoveSubscription(string topicFilter)
32 | {
33 | int index = this.FindSubscriptionIndex(topicFilter);
34 | if (index >= 0)
35 | {
36 | this.subscriptions.RemoveAt(index);
37 | return true;
38 | }
39 | return false;
40 | }
41 |
42 | public bool AddOrUpdateSubscription(string topicFilter, QualityOfService qos)
43 | {
44 | int index = this.FindSubscriptionIndex(topicFilter);
45 |
46 | if (index >= 0)
47 | {
48 | if (this.subscriptions[index].QualityOfService != qos)
49 | {
50 | this.subscriptions[index] = this.subscriptions[index].CreateUpdated(qos);
51 | return true;
52 | }
53 | }
54 | else
55 | {
56 | this.subscriptions.Add(new TransientSubscription(topicFilter, qos));
57 | return true;
58 | }
59 | return false;
60 | }
61 |
62 | int FindSubscriptionIndex(string topicFilter)
63 | {
64 | for (int i = this.subscriptions.Count - 1; i >= 0; i--)
65 | {
66 | ISubscription subscription = this.subscriptions[i];
67 | if (subscription.TopicFilter.Equals(topicFilter, StringComparison.Ordinal))
68 | {
69 | return i;
70 | }
71 | }
72 | return -1;
73 | }
74 | }
75 | }
--------------------------------------------------------------------------------
/src/ProtocolGateway.Core/Mqtt/Persistence/TransientSessionStatePersistenceProvider.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Mqtt.Persistence
5 | {
6 | using System.Threading.Tasks;
7 | using DotNetty.Common.Utilities;
8 | using Microsoft.Azure.Devices.ProtocolGateway.Identity;
9 |
10 | public sealed class TransientSessionStatePersistenceProvider : ISessionStatePersistenceProvider
11 | {
12 | public ISessionState Create(bool transient)
13 | {
14 | return new TransientSessionState(transient);
15 | }
16 |
17 | public Task GetAsync(IDeviceIdentity identity)
18 | {
19 | return Task.FromResult((ISessionState)null);
20 | }
21 |
22 | public Task SetAsync(IDeviceIdentity identity, ISessionState sessionState)
23 | {
24 | return TaskEx.Completed;
25 | }
26 |
27 | public Task DeleteAsync(IDeviceIdentity identity, ISessionState sessionState)
28 | {
29 | return TaskEx.Completed;
30 | }
31 | }
32 | }
--------------------------------------------------------------------------------
/src/ProtocolGateway.Core/Mqtt/Persistence/TransientSubscription.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Mqtt.Persistence
5 | {
6 | using System;
7 | using System.Diagnostics.Contracts;
8 | using DotNetty.Codecs.Mqtt.Packets;
9 |
10 | public class TransientSubscription : ISubscription
11 | {
12 | public TransientSubscription(string topicFilter, QualityOfService qualityOfService)
13 | : this(DateTime.UtcNow, topicFilter, qualityOfService)
14 | {
15 | }
16 |
17 | TransientSubscription(DateTime creationTime, string topicFilter, QualityOfService qualityOfService)
18 | {
19 | this.CreationTime = creationTime;
20 | this.TopicFilter = topicFilter;
21 | this.QualityOfService = qualityOfService;
22 | }
23 |
24 | public DateTime CreationTime { get; }
25 |
26 | public string TopicFilter { get; }
27 |
28 | public QualityOfService QualityOfService { get; }
29 |
30 | [Pure]
31 | public ISubscription CreateUpdated(QualityOfService qos) => new TransientSubscription(this.CreationTime, this.TopicFilter, qos);
32 | }
33 | }
--------------------------------------------------------------------------------
/src/ProtocolGateway.Core/Mqtt/TemplateParameters.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Mqtt
5 | {
6 | public static class TemplateParameters
7 | {
8 | public const string DeviceIdTemplateParam = "deviceId";
9 | }
10 | }
--------------------------------------------------------------------------------
/src/ProtocolGateway.Core/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | using System.Reflection;
5 | using System.Resources;
6 |
7 | [assembly: AssemblyTitle("Microsoft.Azure.Devices.ProtocolGateway.Core")]
8 | [assembly: NeutralResourcesLanguage("en-US")]
9 | [assembly: AssemblyMetadata("Serviceable", "True")]
--------------------------------------------------------------------------------
/src/ProtocolGateway.Core/Properties/Friends.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | using System.Runtime.CompilerServices;
5 |
6 | [assembly: InternalsVisibleTo("Microsoft.Azure.Devices.ProtocolGateway.Tests")]
--------------------------------------------------------------------------------
/src/ProtocolGateway.Core/ProtocolGateway.Core.NetStandard.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard1.3;net451
5 | Microsoft.Azure.Devices.ProtocolGateway.Core
6 | Microsoft Azure IoT protocol gateway framework - Core
7 | This library contains the core components of Azure IoT protocol gateway that enables protocol translation for Azure IoT Hub.
8 | Library
9 | 1.6.1
10 | Microsoft.Azure.Devices.ProtocolGateway.Core
11 | Microsoft.Azure.Devices.ProtocolGateway.Core
12 | 2.2.2.0
13 | 2.2.2
14 | en-US
15 | Microsoft
16 | Microsoft Azure IoT protocol gateway
17 | © Microsoft Corporation. All rights reserved.
18 | Microsoft
19 | http://go.microsoft.com/fwlink/?LinkID=288890
20 | https://github.com/Azure/azure-iot-protocol-gateway/blob/master/LICENSE.txt
21 | https://github.com/Azure/azure-iot-protocol-gateway/
22 | true
23 | Microsoft.Azure.Devices.ProtocolGateway.Core
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/src/ProtocolGateway.Core/ProtocolGatewayException.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway
5 | {
6 | using System;
7 |
8 | public class ProtocolGatewayException : Exception
9 | {
10 | public bool IsTransient { get; }
11 |
12 | public string TrackingId { get; private set; }
13 |
14 | public ErrorCode ErrorCode { get; private set; }
15 |
16 | public ProtocolGatewayException(ErrorCode errorCode, string message)
17 | : this(errorCode, message, false)
18 | {
19 | }
20 |
21 | public ProtocolGatewayException(ErrorCode errorCode, string message, string trackingId)
22 | : this(errorCode, message, false, trackingId)
23 | {
24 | }
25 |
26 | public ProtocolGatewayException(ErrorCode errorCode, string message, bool isTransient)
27 | : this(errorCode, message, isTransient, string.Empty)
28 | {
29 | }
30 |
31 | public ProtocolGatewayException(ErrorCode errorCode, string message, bool isTransient, string trackingId)
32 | : base(message)
33 | {
34 | this.IsTransient = isTransient;
35 | this.TrackingId = trackingId;
36 | this.ErrorCode = errorCode;
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/ProtocolGateway.Core/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/src/ProtocolGateway.IotHubClient/AuthenticationScope.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.IotHubClient
5 | {
6 | public enum AuthenticationScope
7 | {
8 | None,
9 | SasToken,
10 | DeviceKey,
11 | HubKey
12 | }
13 | }
--------------------------------------------------------------------------------
/src/ProtocolGateway.IotHubClient/DeviceClientRetryPolicy.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.IotHubClient
5 | {
6 | using System;
7 | using Microsoft.Azure.Devices.Client;
8 |
9 | public class DeviceClientRetryPolicy : IRetryPolicy
10 | {
11 | public static DeviceClientRetryPolicy Instance { get; } = new DeviceClientRetryPolicy();
12 |
13 | DeviceClientRetryPolicy()
14 | { }
15 |
16 | public bool ShouldRetry(int currentRetryCount, Exception lastException, out TimeSpan retryInterval)
17 | {
18 | // No retry for now. We will tune it as we progress.
19 | retryInterval = TimeSpan.Zero;
20 | return false;
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/ProtocolGateway.IotHubClient/Extensions.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.IotHubClient
5 | {
6 | using Microsoft.Azure.Devices.Client.Exceptions;
7 | using Microsoft.Azure.Devices.ProtocolGateway.Messaging;
8 |
9 | static class Extensions
10 | {
11 | public static MessagingException ToMessagingException(this IotHubException ex)
12 | {
13 | return new MessagingException("Error communicating with IoT Hub. Tracking id: " + ex.TrackingId, ex, ex.IsTransient, ex.TrackingId);
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/ProtocolGateway.IotHubClient/IMessageDispatcher.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.IotHubClient
5 | {
6 | using System.Threading.Tasks;
7 | using Microsoft.Azure.Devices.ProtocolGateway.Messaging;
8 |
9 | public interface IMessageDispatcher
10 | {
11 | Task SendAsync(IMessage message);
12 | }
13 | }
--------------------------------------------------------------------------------
/src/ProtocolGateway.IotHubClient/IotHubClientMessage.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.IotHubClient
5 | {
6 | using System;
7 | using System.Collections.Generic;
8 | using DotNetty.Buffers;
9 | using DotNetty.Common.Utilities;
10 | using Microsoft.Azure.Devices.ProtocolGateway.Messaging;
11 | using Message = Client.Message;
12 |
13 | public sealed class IotHubClientMessage : IMessage
14 | {
15 | readonly Message message;
16 |
17 | public IotHubClientMessage(Message message, IByteBuffer payload)
18 | {
19 | this.message = message;
20 | this.Payload = payload;
21 | }
22 |
23 | public IDictionary Properties => this.message.Properties;
24 |
25 | public string Address { get; set; }
26 |
27 | public IByteBuffer Payload { get; }
28 |
29 | public string Id => this.message.LockToken;
30 |
31 | public DateTime CreatedTimeUtc => this.message.EnqueuedTimeUtc;
32 |
33 | public uint DeliveryCount => this.message.DeliveryCount;
34 |
35 | public ulong SequenceNumber => this.message.SequenceNumber;
36 |
37 | public void Dispose()
38 | {
39 | this.message.Dispose();
40 | if (this.Payload != null)
41 | {
42 | ReferenceCountUtil.SafeRelease(this.Payload);
43 | }
44 | }
45 |
46 | internal Message ToMessage() => this.message;
47 | }
48 | }
--------------------------------------------------------------------------------
/src/ProtocolGateway.IotHubClient/IotHubDeviceIdentity.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.IotHubClient
5 | {
6 | using Microsoft.Azure.Devices.ProtocolGateway.Identity;
7 |
8 | public sealed class IotHubDeviceIdentity : IDeviceIdentity
9 | {
10 | string asString;
11 | string policyName;
12 | AuthenticationScope scope;
13 |
14 | public IotHubDeviceIdentity(string iotHubHostName, string deviceId)
15 | {
16 | this.IotHubHostName = iotHubHostName;
17 | this.Id = deviceId;
18 | }
19 |
20 | public string Id { get; }
21 |
22 | public bool IsAuthenticated => true;
23 |
24 | public string IotHubHostName { get; }
25 |
26 | public string PolicyName
27 | {
28 | get { return this.policyName; }
29 | private set
30 | {
31 | this.policyName = value;
32 | this.asString = null;
33 | }
34 | }
35 |
36 | public string Secret { get; private set; }
37 |
38 | public AuthenticationScope Scope
39 | {
40 | get { return this.scope; }
41 | private set
42 | {
43 | this.scope = value;
44 | this.asString = null;
45 | }
46 | }
47 |
48 | public static bool TryParse(string value, out IotHubDeviceIdentity identity)
49 | {
50 | string[] usernameSegments = value.Split('/');
51 | if (usernameSegments.Length < 2)
52 | {
53 | identity = null;
54 | return false;
55 | }
56 | identity = new IotHubDeviceIdentity(usernameSegments[0], usernameSegments[1]);
57 | return true;
58 | }
59 |
60 | public void WithSasToken(string token)
61 | {
62 | this.Scope = AuthenticationScope.SasToken;
63 | this.Secret = token;
64 | }
65 |
66 | public void WithHubKey(string keyName, string keyValue)
67 | {
68 | this.Scope = AuthenticationScope.HubKey;
69 | this.PolicyName = keyName;
70 | this.Secret = keyValue;
71 | }
72 |
73 | public void WithDeviceKey(string keyValue)
74 | {
75 | this.Scope = AuthenticationScope.DeviceKey;
76 | this.Secret = keyValue;
77 | }
78 |
79 | public override string ToString()
80 | {
81 | if (this.asString == null)
82 | {
83 | string policy = string.IsNullOrEmpty(this.PolicyName) ? "" : this.PolicyName;
84 | this.asString = $"{this.Id} [IotHubHostName: {this.IotHubHostName}; PolicyName: {policy}; Scope: {this.Scope}]";
85 | }
86 | return this.asString;
87 | }
88 | }
89 | }
--------------------------------------------------------------------------------
/src/ProtocolGateway.IotHubClient/KeyDeviceIdentityProvider.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.IotHubClient
5 | {
6 | using System;
7 | using System.Net;
8 | using System.Threading.Tasks;
9 | using Microsoft.Azure.Devices.ProtocolGateway.Identity;
10 |
11 | public sealed class KeyDeviceIdentityProvider : IDeviceIdentityProvider
12 | {
13 | public Task GetAsync(string clientId, string username, string password, EndPoint clientAddress)
14 | {
15 | IotHubDeviceIdentity deviceIdentity;
16 | if (!IotHubDeviceIdentity.TryParse(username, out deviceIdentity) || !clientId.Equals(deviceIdentity.Id, StringComparison.Ordinal))
17 | {
18 | return Task.FromResult(UnauthenticatedDeviceIdentity.Instance);
19 | }
20 | deviceIdentity.WithDeviceKey(password);
21 | return Task.FromResult(deviceIdentity);
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/src/ProtocolGateway.IotHubClient/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | using System.Reflection;
5 | using System.Resources;
6 |
7 | [assembly: AssemblyTitle("Microsoft.Azure.Devices.ProtocolGateway.IotHubClient")]
8 | [assembly: NeutralResourcesLanguage("en-US")]
9 | [assembly: AssemblyMetadata("Serviceable", "True")]
--------------------------------------------------------------------------------
/src/ProtocolGateway.IotHubClient/Properties/Friends.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | using System.Runtime.CompilerServices;
5 |
6 | [assembly: InternalsVisibleTo("Microsoft.Azure.Devices.ProtocolGateway.Tests")]
--------------------------------------------------------------------------------
/src/ProtocolGateway.IotHubClient/ProtocolGateway.IotHubClient.NetStandard.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard1.3;net451
5 | Microsoft.Azure.Devices.ProtocolGateway.IotHubClient
6 | Microsoft Azure IoT protocol gateway framework - IoT Hub client
7 | This library contains Azure IoT Hub specific components of Azure IoT protocol gateway that enables protocol translation for Azure IoT Hub.
8 | Library
9 | 1.6.1
10 | Microsoft.Azure.Devices.ProtocolGateway.IotHubClient
11 | Microsoft.Azure.Devices.ProtocolGateway.IotHubClient
12 | 2.0.1.0
13 | 2.0.1
14 | en-US
15 | Microsoft
16 | Microsoft Azure IoT protocol gateway
17 | © Microsoft Corporation. All rights reserved.
18 | Microsoft
19 | http://go.microsoft.com/fwlink/?LinkID=288890
20 | https://github.com/Azure/azure-iot-protocol-gateway/blob/master/LICENSE.txt
21 | https://github.com/Azure/azure-iot-protocol-gateway/
22 | true
23 | Microsoft.Azure.Devices.ProtocolGateway.IotHubClient
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/src/ProtocolGateway.IotHubClient/SasTokenDeviceIdentityProvider.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.IotHubClient
5 | {
6 | using System;
7 | using System.Net;
8 | using System.Threading.Tasks;
9 | using Microsoft.Azure.Devices.ProtocolGateway.Identity;
10 |
11 | public sealed class SasTokenDeviceIdentityProvider : IDeviceIdentityProvider
12 | {
13 | public Task GetAsync(string clientId, string username, string password, EndPoint clientAddress)
14 | {
15 | IotHubDeviceIdentity deviceIdentity;
16 | if (!IotHubDeviceIdentity.TryParse(username, out deviceIdentity) || !clientId.Equals(deviceIdentity.Id, StringComparison.Ordinal))
17 | {
18 | return Task.FromResult(UnauthenticatedDeviceIdentity.Instance);
19 | }
20 | deviceIdentity.WithSasToken(password);
21 | return Task.FromResult(deviceIdentity);
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/src/ProtocolGateway.IotHubClient/SendMessageOutcome.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.IotHubClient
5 | {
6 | public enum SendMessageOutcome
7 | {
8 | Completed,
9 | Rejected,
10 | }
11 | }
--------------------------------------------------------------------------------
/src/ProtocolGateway.IotHubClient/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/src/ProtocolGateway.Providers.CloudStorage/BlobSessionState.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Providers.CloudStorage
5 | {
6 | using System;
7 | using System.Collections.Generic;
8 | using System.Runtime.Serialization;
9 | using DotNetty.Codecs.Mqtt.Packets;
10 | using Microsoft.Azure.Devices.ProtocolGateway.Mqtt.Persistence;
11 |
12 | class BlobSessionState : ISessionState
13 | {
14 | [DataMember(Name = "subscriptions")] // todo: name casing seems to be ignored by the serializer
15 | readonly List subscriptions;
16 |
17 | public BlobSessionState(bool transient)
18 | {
19 | this.IsTransient = transient;
20 | this.subscriptions = new List();
21 | }
22 |
23 | [IgnoreDataMember]
24 | public bool IsTransient { get; }
25 |
26 | public IReadOnlyList Subscriptions => this.subscriptions;
27 |
28 | [IgnoreDataMember]
29 | public string ETag { get; set; }
30 |
31 | public ISessionState Copy()
32 | {
33 | var sessionState = new BlobSessionState(this.IsTransient);
34 | sessionState.ETag = this.ETag;
35 | sessionState.subscriptions.AddRange(this.Subscriptions);
36 | return sessionState;
37 | }
38 |
39 | public bool RemoveSubscription(string topicFilter)
40 | {
41 | int index = this.FindSubscriptionIndex(topicFilter);
42 | if (index >= 0)
43 | {
44 | this.subscriptions.RemoveAt(index);
45 | return true;
46 | }
47 | return false;
48 | }
49 |
50 | public bool AddOrUpdateSubscription(string topicFilter, QualityOfService qos)
51 | {
52 | int index = this.FindSubscriptionIndex(topicFilter);
53 |
54 | if (index >= 0)
55 | {
56 | if (this.subscriptions[index].QualityOfService != qos)
57 | {
58 | this.subscriptions[index] = this.subscriptions[index].CreateUpdated(qos);
59 | return true;
60 | }
61 | }
62 | else
63 | {
64 | this.subscriptions.Add(new Subscription(topicFilter, qos));
65 | return true;
66 | }
67 | return false;
68 | }
69 |
70 | int FindSubscriptionIndex(string topicFilter)
71 | {
72 | for (int i = this.subscriptions.Count - 1; i >= 0; i--)
73 | {
74 | ISubscription subscription = this.subscriptions[i];
75 | if (subscription.TopicFilter.Equals(topicFilter, StringComparison.Ordinal))
76 | {
77 | return i;
78 | }
79 | }
80 | return -1;
81 | }
82 | }
83 | }
--------------------------------------------------------------------------------
/src/ProtocolGateway.Providers.CloudStorage/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | using System.Reflection;
5 | using System.Resources;
6 | using System.Runtime.InteropServices;
7 |
8 | // General Information about an assembly is controlled through the following
9 | // set of attributes. Change these attribute values to modify the information
10 | // associated with an assembly.
11 |
12 | [assembly: AssemblyTitle("Microsoft.Azure.Devices.ProtocolGateway.Providers.CloudStorage")]
13 | [assembly: NeutralResourcesLanguage("en-US")]
14 | [assembly: AssemblyMetadata("Serviceable", "True")]
15 |
16 | // Setting ComVisible to false makes the types in this assembly not visible
17 | // to COM components. If you need to access a type in this assembly from
18 | // COM, set the ComVisible attribute to true on that type.
19 |
20 | [assembly: ComVisible(false)]
--------------------------------------------------------------------------------
/src/ProtocolGateway.Providers.CloudStorage/ProtocolGateway.Providers.CloudStorage.NetStandard.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard1.4;net451
5 | Microsoft.Azure.Devices.ProtocolGateway.Providers.CloudStorage
6 | Microsoft Azure IoT protocol gateway framework - Azure Storage persistence providers
7 | This library contains the Azure Storage-based persistence components of Azure IoT protocol gateway that enables protocol translation for Azure IoT Hub.
8 | Library
9 | 1.6.1
10 | Microsoft.Azure.Devices.ProtocolGateway.Providers.CloudStorage
11 | Microsoft.Azure.Devices.ProtocolGateway.Providers.CloudStorage
12 | 2.0.1.0
13 | 2.0.1
14 | en-US
15 | Microsoft
16 | Microsoft Azure IoT protocol gateway
17 | © Microsoft Corporation. All rights reserved.
18 | Microsoft
19 | http://go.microsoft.com/fwlink/?LinkID=288890
20 | https://github.com/Azure/azure-iot-protocol-gateway/blob/master/LICENSE.txt
21 | https://github.com/Azure/azure-iot-protocol-gateway/
22 | true
23 | Microsoft.Azure.Devices.ProtocolGateway.Providers.CloudStorage
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/src/ProtocolGateway.Providers.CloudStorage/Subscription.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Providers.CloudStorage
5 | {
6 | using System;
7 | using System.Diagnostics.Contracts;
8 | using DotNetty.Codecs.Mqtt.Packets;
9 | using Microsoft.Azure.Devices.ProtocolGateway.Mqtt.Persistence;
10 | using Newtonsoft.Json;
11 |
12 | public class Subscription : ISubscription
13 | {
14 | public Subscription(string topicFilter, QualityOfService qualityOfService)
15 | : this(DateTime.UtcNow, topicFilter, qualityOfService)
16 | {
17 | }
18 |
19 | Subscription(DateTime creationTime, string topicFilter, QualityOfService qualityOfService)
20 | {
21 | this.CreationTime = creationTime;
22 | this.TopicFilter = topicFilter;
23 | this.QualityOfService = qualityOfService;
24 | }
25 |
26 | internal Subscription()
27 | {}
28 |
29 |
30 | [JsonProperty]
31 | public DateTime CreationTime { get; private set; }
32 |
33 | [JsonProperty]
34 | public string TopicFilter { get; private set; }
35 |
36 | [JsonProperty]
37 | public QualityOfService QualityOfService { get; private set; }
38 |
39 | [Pure]
40 | public ISubscription CreateUpdated(QualityOfService qos) => new Subscription(this.CreationTime, this.TopicFilter, qos);
41 | }
42 | }
--------------------------------------------------------------------------------
/src/ProtocolGateway.Providers.CloudStorage/TableMessageDeliveryState.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Providers.CloudStorage
5 | {
6 | using System;
7 | using Microsoft.Azure.Devices.ProtocolGateway.Mqtt.Persistence;
8 | using Microsoft.WindowsAzure.Storage.Table;
9 |
10 | class TableMessageDeliveryState : TableEntity, IQos2MessageDeliveryState
11 | {
12 | public TableMessageDeliveryState()
13 | {
14 | }
15 |
16 | public TableMessageDeliveryState(ulong sequenceNumber)
17 | {
18 | this.MessageNumber = unchecked ((long)sequenceNumber);
19 | this.LastModified = DateTime.UtcNow;
20 | }
21 |
22 | public DateTime LastModified
23 | {
24 | get { return this.Timestamp.UtcDateTime; }
25 | set { this.Timestamp = value; }
26 | }
27 |
28 | public long MessageNumber { get; set; }
29 |
30 | ulong IQos2MessageDeliveryState.SequenceNumber => unchecked((ulong)this.MessageNumber);
31 | }
32 | }
--------------------------------------------------------------------------------
/src/ProtocolGateway.Providers.CloudStorage/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/src/SharedAssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | using System.Reflection;
5 |
6 | [assembly: AssemblyCompany("Microsoft")]
7 | [assembly: AssemblyCopyright("Copyright © Microsoft 2015")]
8 | [assembly: AssemblyVersion("1.0.0.0")]
9 | [assembly: AssemblyFileVersion("1.0.0.0")]
10 | [assembly: AssemblyProduct("Microsoft Azure IoT protocol gateway")]
--------------------------------------------------------------------------------
/test/ProtocolGateway.Client.NetStandard/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | using System.Reflection;
5 | using System.Resources;
6 |
7 | [assembly: NeutralResourcesLanguage("en-US")]
8 | [assembly: AssemblyMetadata("Serviceable", "True")]
--------------------------------------------------------------------------------
/test/ProtocolGateway.Client.NetStandard/ProtocolGateway.Client.NetStandard.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | exe
6 | netcoreapp1.1
7 |
8 | exe
9 |
10 | ProtocolGateway.Client
11 | ProtocolGateway.Client
12 | 1.0.0.0
13 | Microsoft
14 | Copyright © Microsoft 2015
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/test/ProtocolGateway.Tests.Load/ConsoleLoggingHandler.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Tests.Load
5 | {
6 | using System;
7 | using DotNetty.Transport.Channels;
8 |
9 | public class ConsoleLoggingHandler : ChannelHandlerAdapter
10 | {
11 | ConsoleLoggingHandler()
12 | {
13 | }
14 |
15 | public static ConsoleLoggingHandler Instance { get; } = new ConsoleLoggingHandler();
16 |
17 | public override bool IsSharable => true;
18 |
19 | public override void UserEventTriggered(IChannelHandlerContext context, object evt)
20 | {
21 | Console.WriteLine($"User Event: {evt}");
22 | base.UserEventTriggered(context, evt);
23 | }
24 |
25 | public override void ExceptionCaught(IChannelHandlerContext context, Exception exception)
26 | {
27 | Console.WriteLine($"Exception: {exception}");
28 | base.ExceptionCaught(context, exception);
29 | }
30 | }
31 | }
--------------------------------------------------------------------------------
/test/ProtocolGateway.Tests.Load/EnumerableExtensions.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Tests.Load
5 | {
6 | using System.Collections.Generic;
7 | using System.Linq;
8 |
9 | static class EnumerableExtensions
10 | {
11 | public static IEnumerable> InSetsOf(this IEnumerable source, int maxSize)
12 | {
13 | var result = new List(maxSize);
14 | foreach (T item in source)
15 | {
16 | result.Add(item);
17 | if (result.Count == maxSize)
18 | {
19 | yield return result;
20 | result = new List(maxSize);
21 | }
22 | }
23 | if (result.Any())
24 | {
25 | yield return result;
26 | }
27 | }
28 | }
29 | }
--------------------------------------------------------------------------------
/test/ProtocolGateway.Tests.Load/IdProvider.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Tests.Load
5 | {
6 | using System.Threading;
7 |
8 | class IdProvider
9 | {
10 | readonly string idPattern;
11 | int lastId;
12 |
13 | public IdProvider(int from, string idPattern)
14 | {
15 | this.idPattern = idPattern;
16 | this.lastId = from - 1;
17 | }
18 |
19 | public string Get()
20 | {
21 | return string.Format(this.idPattern, Interlocked.Increment(ref this.lastId));
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/test/ProtocolGateway.Tests.Load/OccasionalTelemetryRunner.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Tests.Load
5 | {
6 | using System;
7 | using System.Net;
8 | using System.Threading;
9 | using System.Threading.Tasks;
10 | using DotNetty.Codecs.Mqtt.Packets;
11 | using DotNetty.Transport.Channels;
12 |
13 | class OccasionalTelemetryRunner : DeviceRunner
14 | {
15 | public OccasionalTelemetryRunner(IEventLoopGroup eventLoopGroup, string deviceKey, string iotHubConnectionString, IPEndPoint endpoint, string tlsHostName)
16 | : base(eventLoopGroup, deviceKey, iotHubConnectionString, endpoint, tlsHostName)
17 | {
18 | }
19 |
20 | protected override string Name => "occasional";
21 |
22 | protected override async Task GetScenario(IChannel channel, ReadListeningHandler readHandler, string clientId,
23 | CancellationToken cancellationToken)
24 | {
25 | await GetSubscribeSteps(channel, readHandler, clientId);
26 |
27 | await GetPublishSteps(channel, readHandler, clientId, QualityOfService.AtLeastOnce, "devices/{0}/messages/events", 10, 138, 353);
28 | }
29 |
30 | public override async Task OnClosedAsync(string deviceId, Exception exception, bool onStart)
31 | {
32 | if (exception != null)
33 | {
34 | return await base.OnClosedAsync(deviceId, exception, onStart);
35 | }
36 |
37 | await Task.Delay(TimeSpan.FromMinutes(10) + TimeSpan.FromSeconds(Random.Next(-5, 6))); // 10 min +/- 5 sec
38 | return true;
39 | }
40 | }
41 | }
--------------------------------------------------------------------------------
/test/ProtocolGateway.Tests.Load/Options.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Tests.Load
5 | {
6 | using CommandLine;
7 |
8 | class Options
9 | {
10 | [OptionArray('r', "runners", HelpText = "runners configuration in a form of threes: name start-frequency count. Known scenarios are \"stable\", \"occasional\"")]
11 | public string[] Runners { get; set; }
12 |
13 | //[Option('m', "multiply", DefaultValue = 1, HelpText = "multiplication factor per scenario numbers.")]
14 | //public int Multiply { get; set; }
15 |
16 | //[Option('l', "latency", DefaultValue = 40, HelpText = "latency per connection, msec.")]
17 | //public int Latency { get; set; }
18 |
19 | [Option('a', "address", DefaultValue = "127.0.0.1", HelpText = "address to connect to.")]
20 | public string Address { get; set; }
21 |
22 | [Option('p', "port", DefaultValue = 8883, HelpText = "port to connect to.")]
23 | public int Port { get; set; }
24 |
25 | [Option('c', "connection", HelpText = "IoT Hub connection string (without DeviceId).")]
26 | public string IotHubConnectionString { get; set; }
27 |
28 | [Option('h', "hostname", HelpText = "Protocol Gateway host name.")]
29 | public string HostName { get; set; }
30 |
31 | [Option("createdevices", DefaultValue = 0, HelpText = "specifies number of test devices to create.")]
32 | public int CreateDeviceCount { get; set; }
33 |
34 | [Option('s', "devicesfrom", DefaultValue = 1, HelpText = "specifies initial counter value to use for test devices creation and initialization.")]
35 | public int DeviceStartingFrom { get; set; }
36 |
37 | [Option("devicenamepattern", DefaultValue = "testdevice_{0}", HelpText = "specifies name pattern to use for newly created devices. Use \"{0}\" as a placeholder for running counter.")]
38 | public string DeviceNamePattern { get; set; }
39 |
40 | [Option("devicekey", HelpText = "specifies primary key value to use for newly created devices.")]
41 | public string DeviceKey { get; set; }
42 |
43 | [Option("devicekey2", HelpText = "specifies secondary key value to use for newly created devices.")]
44 | public string DeviceKey2 { get; set; }
45 | }
46 | }
--------------------------------------------------------------------------------
/test/ProtocolGateway.Tests.Load/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Gateway.Tests.Load")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("Gateway.Tests.Load")]
13 | [assembly: AssemblyCopyright("Copyright © 2015")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("be074eb4-c7ab-42d4-8841-29117cc44983")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/test/ProtocolGateway.Tests.Load/RunnerConfiguration.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Tests.Load
5 | {
6 | using System;
7 | using System.Threading;
8 | using System.Threading.Tasks;
9 |
10 | public class RunnerConfiguration
11 | {
12 | public RunnerConfiguration(string name, Func> startFunc,
13 | Func> closedFunc, int count, TimeSpan rampUpPeriod)
14 | {
15 | this.StartFunc = startFunc;
16 | this.ClosedFunc = closedFunc;
17 | this.Count = count;
18 | this.RampUpPeriod = rampUpPeriod;
19 | this.Name = name;
20 | }
21 |
22 | public string Name { get; private set; }
23 |
24 | public int Count { get; private set; }
25 |
26 | public TimeSpan RampUpPeriod { get; private set; }
27 |
28 | ///
29 | /// in: id, out: future for start completion wrapping future for subsequent closure
30 | ///
31 | public Func> StartFunc { get; private set; }
32 |
33 | ///
34 | /// in: Exception on closure (if any), out: future task for decision whether to restart the runner; future can be used
35 | /// to delay execution
36 | ///
37 | public Func> ClosedFunc { get; private set; }
38 | }
39 | }
--------------------------------------------------------------------------------
/test/ProtocolGateway.Tests.Load/StableTelemetryRunner.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Tests.Load
5 | {
6 | using System;
7 | using System.Net;
8 | using System.Threading;
9 | using System.Threading.Tasks;
10 | using DotNetty.Codecs.Mqtt.Packets;
11 | using DotNetty.Transport.Channels;
12 |
13 | class StableTelemetryRunner : DeviceRunner
14 | {
15 | public StableTelemetryRunner(IEventLoopGroup eventLoopGroup, string deviceKey, string iotHubConnectionString, IPEndPoint endpoint, string tlsHostName)
16 | : base(eventLoopGroup, deviceKey, iotHubConnectionString, endpoint, tlsHostName)
17 | {
18 | }
19 |
20 | protected override string Name => "stable";
21 |
22 | protected override async Task GetScenario(IChannel channel, ReadListeningHandler readHandler, string clientId,
23 | CancellationToken cancellationToken)
24 | {
25 | await GetSubscribeSteps(channel, readHandler, clientId);
26 |
27 | while (!cancellationToken.IsCancellationRequested)
28 | {
29 | await GetPublishSteps(channel, readHandler, clientId, QualityOfService.AtLeastOnce, "devices/{0}/messages/events", 1, 138, 353);
30 |
31 | await channel.EventLoop.ScheduleAsync(() => { }, TimeSpan.FromMinutes(1), cancellationToken);
32 | }
33 | }
34 | }
35 | }
--------------------------------------------------------------------------------
/test/ProtocolGateway.Tests.Load/TaskExtensions.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Tests.Load
5 | {
6 | using System;
7 | using System.Threading.Tasks;
8 |
9 | static class TaskExtensions
10 | {
11 | public static void LogOnFaulure(this Task task)
12 | {
13 | task.ContinueWith(
14 | t =>
15 | {
16 | // todo: log
17 | Console.WriteLine(t.Exception);
18 | },
19 | TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.OnlyOnFaulted);
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------
/test/ProtocolGateway.Tests/ChannelExtensions.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Tests
5 | {
6 | using System.Collections.Generic;
7 | using System.Threading.Tasks;
8 | using DotNetty.Transport.Channels;
9 |
10 | public static class ChannelExtensions
11 | {
12 | public static Task WriteAndFlushManyAsync(this IChannel channel, params object[] messages)
13 | {
14 | var list = new List();
15 | foreach (object m in messages)
16 | {
17 | list.Add(channel.WriteAsync(m));
18 | }
19 | IEnumerable tasks = list.ToArray();
20 | channel.Flush();
21 | return Task.WhenAll(tasks);
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/test/ProtocolGateway.Tests/DiagnosticsTests.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Tests
5 | {
6 | using global::ProtocolGateway.Host.Common;
7 | using Microsoft.Azure.Devices.ProtocolGateway.Instrumentation;
8 | using Microsoft.Practices.EnterpriseLibrary.SemanticLogging.Utility;
9 | using Xunit;
10 |
11 | public class DiagnosticsTests
12 | {
13 | [Fact]
14 | public void VerifyEventSources()
15 | {
16 | EventSourceAnalyzer.InspectAll(CommonEventSource.Log);
17 | EventSourceAnalyzer.InspectAll(BootstrapperEventSource.Log);
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/test/ProtocolGateway.Tests/Extensions/ByteBufferExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace Microsoft.Azure.Devices.ProtocolGateway.Tests.Extensions
2 | {
3 | using DotNetty.Buffers;
4 | using DotNetty.Common.Utilities;
5 | using System;
6 |
7 | public static class ByteBufferExtensions
8 | {
9 | public static byte[] ToArray(this IByteBuffer buffer)
10 | {
11 | if (!buffer.IsReadable())
12 | {
13 | return ArrayExtensions.ZeroBytes;
14 | }
15 | var segment = buffer.GetIoBuffer();
16 | var result = new byte[segment.Count];
17 | Array.Copy(segment.Array, segment.Offset, result, 0, segment.Count);
18 | return result;
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/test/ProtocolGateway.Tests/Extensions/TaskExtensions.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Tests.Extensions
5 | {
6 | using System;
7 | using System.Threading;
8 | using System.Threading.Tasks;
9 |
10 | public static class TaskExtensions
11 | {
12 | public static Task WithTimeout(this Task task, TimeSpan timeout)
13 | {
14 | if (task.IsCompleted || (timeout == Timeout.InfiniteTimeSpan))
15 | {
16 | return task;
17 | }
18 |
19 | return WithTimeoutInternal(task, timeout);
20 | }
21 |
22 | static async Task WithTimeoutInternal(Task task, TimeSpan timeout)
23 | {
24 | using (var cts = new CancellationTokenSource())
25 | {
26 | if (task == await Task.WhenAny(task, Task.Delay(timeout, cts.Token)))
27 | {
28 | cts.Cancel();
29 | await task;
30 | return;
31 | }
32 | }
33 |
34 | throw new TimeoutException();
35 | }
36 | }
37 | }
--------------------------------------------------------------------------------
/test/ProtocolGateway.Tests/MqttTopicMatchingTests.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Tests
5 | {
6 | using System;
7 | using System.Collections.Generic;
8 | using Microsoft.Azure.Devices.ProtocolGateway.Mqtt;
9 | using Xunit;
10 |
11 | public class MqttTopicMatchingTests
12 | {
13 | [Theory]
14 | [InlineData("abc/def", "abc/def", true)]
15 | [InlineData("abc/def", "+/+", true)]
16 | [InlineData("abc/def", "abc/def/#", true)]
17 | [InlineData("abc/def", "abc/defg/#", false)]
18 | [InlineData("abc/defg", "abc/def", false)]
19 | [InlineData("sports/tennis/player1", "sports/tennis/player1/#", true)]
20 | [InlineData("sports/tennis/player1/ranking", "sports/tennis/player1/#", true)]
21 | [InlineData("sports/tennis/player1/score/wimbledon", "sports/tennis/player1/#", true)]
22 | [InlineData("sports/tennis/player1", "sports/tennis/#", true)]
23 | [InlineData("sports", "sports/#", true)]
24 | [InlineData("sport/tennis/player1", "sport/tennis/+", true)]
25 | [InlineData("sport/tennis/", "sport/tennis/+", true)]
26 | [InlineData("sport/tennis", "sport/tennis/+", false)]
27 | [InlineData("sport/tennis/player1/ranking", "sport/tennis/+", false)]
28 | [InlineData("/a/bbb/c", "/a/+/c", true)]
29 | [InlineData("///", "+/+/+/", true)]
30 | [InlineData("/", "+", false)]
31 | [InlineData("/a", "+/a", true)]
32 | [InlineData("abc/a", "+/a", true)]
33 | [InlineData("a/a", "+/a", true)]
34 | [InlineData("/a/bc/c", "/a/+/c", true)]
35 | [InlineData("a", "#", true)]
36 | [InlineData("/", "#", true)]
37 | [InlineData("abc/def", "#", true)]
38 | public void MqttTopicMatchTest(string topicName, string topicFilter, bool expectedResult)
39 | {
40 | bool result = Util.CheckTopicFilterMatch(topicName, topicFilter);
41 | Assert.Equal(expectedResult, result);
42 | }
43 |
44 | [Fact]
45 | public void Experiment()
46 | {
47 | var template = new UriTemplate("devices/{deviceId}/messages/outbound/{*subTopic}");
48 | var baseUri = new Uri("http://whatever");
49 | Uri bound = template.BindByName(baseUri, new Dictionary
50 | {
51 | { "deviceId", "VINno" },
52 | { "SubTopic", "toptop/toptoptop" },
53 | });
54 | var t2 = new UriTemplate("devices/{deviceId}/messages/log/{level=info}/{subject=n%2Fa}", true);
55 | UriTemplateMatch match = t2.Match(baseUri, new Uri("http://whatever/devices/VINno/messages/log", UriKind.Absolute));
56 | }
57 | }
58 | }
--------------------------------------------------------------------------------
/test/ProtocolGateway.Tests/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | using System.Reflection;
5 | using System.Resources;
6 |
7 | [assembly: NeutralResourcesLanguage("en-US")]
8 | [assembly: AssemblyMetadata("Serviceable", "True")]
--------------------------------------------------------------------------------
/test/ProtocolGateway.Tests/ReadListeningHandler.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Azure.Devices.ProtocolGateway.Tests
5 | {
6 | using System;
7 | using System.Collections.Concurrent;
8 | using System.Collections.Generic;
9 | using System.Threading.Tasks;
10 | using DotNetty.Transport.Channels;
11 |
12 | public sealed class ReadListeningHandler : ChannelHandlerAdapter
13 | {
14 | readonly Queue