diff --git a/azureiot.sln b/azureiot.sln
index 0b45546187..f5a83728d4 100644
--- a/azureiot.sln
+++ b/azureiot.sln
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 16.0.29709.97
+# Visual Studio Version 17
+VisualStudioVersion = 17.1.32328.378
MinimumVisualStudioVersion = 15.0.26124.0
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "iothub", "iothub", "{537FA828-124D-4C70-9FC1-89301D9E776D}"
EndProject
diff --git a/e2e/test/iothub/FileUploadE2ETests.cs b/e2e/test/iothub/FileUploadE2ETests.cs
index d461b0788b..f0fdbaade0 100644
--- a/e2e/test/iothub/FileUploadE2ETests.cs
+++ b/e2e/test/iothub/FileUploadE2ETests.cs
@@ -2,7 +2,6 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
-using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Net;
using System.Security.Cryptography.X509Certificates;
@@ -52,6 +51,14 @@ public async Task FileUpload_GetFileUploadSasUri_Http_x509_NoFileTransportSettin
await GetSasUriAsync(Client.TransportType.Http1, smallFileBlobName, true).ConfigureAwait(false);
}
+ [LoggedTestMethod]
+ [TestCategory("LongRunning")]
+ public async Task FileUpload_GetFileUploadSasUri_Mqtt_x509_NoFileTransportSettingSpecified()
+ {
+ string smallFileBlobName = await GetTestFileNameAsync(FileSizeSmall).ConfigureAwait(false);
+ await GetSasUriAsync(Client.TransportType.Mqtt, smallFileBlobName, true).ConfigureAwait(false);
+ }
+
[LoggedTestMethod]
[TestCategory("LongRunning")]
[Obsolete]
@@ -200,10 +207,14 @@ private async Task UploadFileAsync(Client.TransportType transport, string filena
private async Task GetSasUriAsync(Client.TransportType transport, string blobName, bool useX509auth = false)
{
- using TestDevice testDevice = await TestDevice.GetTestDeviceAsync(
- Logger,
- _devicePrefix,
- useX509auth ? TestDeviceType.X509 : TestDeviceType.Sasl).ConfigureAwait(false);
+ using TestDevice testDevice = await TestDevice
+ .GetTestDeviceAsync(
+ Logger,
+ _devicePrefix,
+ useX509auth
+ ? TestDeviceType.X509
+ : TestDeviceType.Sasl)
+ .ConfigureAwait(false);
DeviceClient deviceClient;
X509Certificate2 cert = null;
diff --git a/iothub/device/src/AuthenticationMethodFactory.cs b/iothub/device/src/AuthenticationMethodFactory.cs
index c371040a20..11bb1b46db 100644
--- a/iothub/device/src/AuthenticationMethodFactory.cs
+++ b/iothub/device/src/AuthenticationMethodFactory.cs
@@ -11,43 +11,48 @@ namespace Microsoft.Azure.Devices.Client
///
public sealed class AuthenticationMethodFactory
{
- internal static IAuthenticationMethod GetAuthenticationMethod(IotHubConnectionStringBuilder iotHubConnectionStringBuilder)
+ internal static IAuthenticationMethod GetAuthenticationMethod(IotHubConnectionStringBuilder csBuilder)
{
- if (iotHubConnectionStringBuilder.SharedAccessKeyName != null)
+ if (csBuilder.SharedAccessKeyName != null)
{
return new DeviceAuthenticationWithSharedAccessPolicyKey(
- iotHubConnectionStringBuilder.DeviceId, iotHubConnectionStringBuilder.SharedAccessKeyName, iotHubConnectionStringBuilder.SharedAccessKey);
+ csBuilder.DeviceId,
+ csBuilder.SharedAccessKeyName,
+ csBuilder.SharedAccessKey);
}
- else if (iotHubConnectionStringBuilder.SharedAccessKey != null)
+ else if (csBuilder.SharedAccessKey != null)
{
- if (iotHubConnectionStringBuilder.ModuleId != null)
+ if (csBuilder.ModuleId != null)
{
return new ModuleAuthenticationWithRegistrySymmetricKey(
- iotHubConnectionStringBuilder.DeviceId, iotHubConnectionStringBuilder.ModuleId, iotHubConnectionStringBuilder.SharedAccessKey);
+ csBuilder.DeviceId,
+ csBuilder.ModuleId,
+ csBuilder.SharedAccessKey);
}
else
{
return new DeviceAuthenticationWithRegistrySymmetricKey(
- iotHubConnectionStringBuilder.DeviceId, iotHubConnectionStringBuilder.SharedAccessKey);
+ csBuilder.DeviceId,
+ csBuilder.SharedAccessKey);
}
}
- else if (iotHubConnectionStringBuilder.SharedAccessSignature != null)
+ else if (csBuilder.SharedAccessSignature != null)
{
- return iotHubConnectionStringBuilder.ModuleId != null
+ return csBuilder.ModuleId != null
? new ModuleAuthenticationWithToken(
- iotHubConnectionStringBuilder.DeviceId,
- iotHubConnectionStringBuilder.ModuleId,
- iotHubConnectionStringBuilder.SharedAccessSignature)
+ csBuilder.DeviceId,
+ csBuilder.ModuleId,
+ csBuilder.SharedAccessSignature)
: (IAuthenticationMethod)new DeviceAuthenticationWithToken(
- iotHubConnectionStringBuilder.DeviceId,
- iotHubConnectionStringBuilder.SharedAccessSignature);
+ csBuilder.DeviceId,
+ csBuilder.SharedAccessSignature);
}
- else if (iotHubConnectionStringBuilder.UsingX509Cert)
+ else if (csBuilder.UsingX509Cert)
{
- return new DeviceAuthenticationWithX509Certificate(iotHubConnectionStringBuilder.DeviceId, iotHubConnectionStringBuilder.Certificate);
+ return new DeviceAuthenticationWithX509Certificate(csBuilder.DeviceId, csBuilder.Certificate);
}
- throw new InvalidOperationException("Unsupported Authentication Method {0}".FormatInvariant(iotHubConnectionStringBuilder));
+ throw new InvalidOperationException($"Unsupported authentication method in '{csBuilder}'.");
}
///
diff --git a/iothub/device/src/ClientFactory.cs b/iothub/device/src/ClientFactory.cs
index 3ab6d9b710..ef27d6f884 100644
--- a/iothub/device/src/ClientFactory.cs
+++ b/iothub/device/src/ClientFactory.cs
@@ -3,6 +3,7 @@
using System;
using System.Linq;
+using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.Text.RegularExpressions;
using Microsoft.Azure.Devices.Client.Exceptions;
@@ -122,12 +123,14 @@ internal static InternalClient Create(
throw new ArgumentException("No certificate was found. To use certificate authentication certificate must be present.");
}
- InternalClient dc = CreateFromConnectionString(
+ InternalClient internalClient = CreateFromConnectionString(
connectionStringBuilder.ToString(),
+ authenticationMethod,
PopulateCertificateInTransportSettings(connectionStringBuilder, transportType),
+ null,
options);
- dc.Certificate = connectionStringBuilder.Certificate;
+ internalClient.Certificate = connectionStringBuilder.Certificate;
// Install all the intermediate certificates in the chain if specified.
if (connectionStringBuilder.ChainCertificates != null)
@@ -143,7 +146,7 @@ internal static InternalClient Create(
}
}
- return dc;
+ return internalClient;
}
return CreateFromConnectionString(connectionStringBuilder.ToString(), authenticationMethod, transportType, null, options);
@@ -296,7 +299,7 @@ internal static InternalClient CreateFromConnectionString(
throw new ArgumentException("Connection string must not contain DeviceId keyvalue parameter", nameof(connectionString));
}
- return CreateFromConnectionString(connectionString + ";" + DeviceId + "=" + deviceId, transportType, options);
+ return CreateFromConnectionString($"{connectionString};{DeviceId}={deviceId}", transportType, options);
}
///
@@ -306,8 +309,10 @@ internal static InternalClient CreateFromConnectionString(
/// Prioritized list of transports and their settings
/// The options that allow configuration of the device client instance during initialization.
/// InternalClient
- internal static InternalClient CreateFromConnectionString(string connectionString,
- ITransportSettings[] transportSettings, ClientOptions options = default)
+ internal static InternalClient CreateFromConnectionString(
+ string connectionString,
+ ITransportSettings[] transportSettings,
+ ClientOptions options = default)
{
return CreateFromConnectionString(connectionString, null, transportSettings, null, options);
}
@@ -317,10 +322,14 @@ internal static InternalClient CreateFromConnectionString(string connectionStrin
///
/// Connection string for the IoT hub (without DeviceId)
/// Id of the device
- /// Prioritized list of transportTypes and their settings
+ /// Prioritized list of transport types and their settings
/// The options that allow configuration of the device client instance during initialization.
/// InternalClient
- internal static InternalClient CreateFromConnectionString(string connectionString, string deviceId, ITransportSettings[] transportSettings, ClientOptions options = default)
+ internal static InternalClient CreateFromConnectionString(
+ string connectionString,
+ string deviceId,
+ ITransportSettings[] transportSettings,
+ ClientOptions options = default)
{
if (connectionString == null)
{
@@ -337,7 +346,7 @@ internal static InternalClient CreateFromConnectionString(string connectionStrin
throw new ArgumentException("Connection string must not contain DeviceId keyvalue parameter", nameof(connectionString));
}
- return CreateFromConnectionString(connectionString + ";" + DeviceId + "=" + deviceId, transportSettings, options);
+ return CreateFromConnectionString($"{connectionString};{DeviceId}={deviceId}", transportSettings, options);
}
internal static InternalClient CreateFromConnectionString(
@@ -430,8 +439,9 @@ internal static InternalClient CreateFromConnectionString(
// Clients that derive their authentication method from AuthenticationWithTokenRefresh will need to specify
// the token time to live and renewal buffer values through the corresponding AuthenticationWithTokenRefresh
- // implementation constructors instead.
- if (!(builder.AuthenticationMethod is AuthenticationWithTokenRefresh))
+ // implementation constructors instead, and these values are irrelevant for cert-based auth.
+ if (!(builder.AuthenticationMethod is AuthenticationWithTokenRefresh)
+ && !(builder.AuthenticationMethod is DeviceAuthenticationWithX509Certificate))
{
builder.SasTokenTimeToLive = options?.SasTokenTimeToLive ?? default;
builder.SasTokenRenewalBuffer = options?.SasTokenRenewalBuffer ?? default;
@@ -501,17 +511,20 @@ internal static InternalClient CreateFromConnectionString(
///
private static void EnsureOptionsIsSetup(X509Certificate2 cert, ref ClientOptions options)
{
- if (options?.FileUploadTransportSettings == null)
+ if (options == null)
{
- var fileUploadTransportSettings = new Http1TransportSettings { ClientCertificate = cert };
- if (options == null)
- {
- options = new ClientOptions { FileUploadTransportSettings = fileUploadTransportSettings };
- }
- else
- {
- options.FileUploadTransportSettings = fileUploadTransportSettings;
- }
+ options = new ClientOptions();
+ }
+
+ if (options.FileUploadTransportSettings == null)
+ {
+ options.FileUploadTransportSettings = new Http1TransportSettings();
+ }
+
+ if (cert != null
+ && options.FileUploadTransportSettings.ClientCertificate == null)
+ {
+ options.FileUploadTransportSettings.ClientCertificate = cert;
}
}
diff --git a/iothub/device/src/ClientOptions.cs b/iothub/device/src/ClientOptions.cs
index 8f6fd9cd0e..1953bded96 100644
--- a/iothub/device/src/ClientOptions.cs
+++ b/iothub/device/src/ClientOptions.cs
@@ -19,9 +19,9 @@ public class ClientOptions
///
/// The transport settings to use for all file upload operations, regardless of what protocol the device
- /// client is configured with. All file upload operations take place over https.
- /// If FileUploadTransportSettings is not provided, then file upload operations will use the client certificates configured
- /// in the transport settings set for the non-file upload operations.
+ /// client is configured with. All file upload operations take place over https.
+ /// If FileUploadTransportSettings is not provided, then file upload operations will use the same client certificates
+ /// configured in the transport settings set for client connect.
///
public Http1TransportSettings FileUploadTransportSettings { get; set; } = new Http1TransportSettings();
diff --git a/iothub/device/src/InternalClient.cs b/iothub/device/src/InternalClient.cs
index 67ec4b8533..28c8f15757 100644
--- a/iothub/device/src/InternalClient.cs
+++ b/iothub/device/src/InternalClient.cs
@@ -159,8 +159,9 @@ public InternalClient(IotHubConnectionString iotHubConnectionString, ITransportS
TlsVersions.Instance.SetLegacyAcceptableVersions();
- IotHubConnectionString = iotHubConnectionString;
+ _transportSettings = transportSettings;
_clientOptions = options;
+ IotHubConnectionString = iotHubConnectionString;
var pipelineContext = new PipelineContext();
pipelineContext.Set(transportSettings);
@@ -176,25 +177,17 @@ public InternalClient(IotHubConnectionString iotHubConnectionString, ITransportS
IDelegatingHandler innerHandler = pipelineBuilder.Build(pipelineContext);
if (Logging.IsEnabled)
- {
Logging.Associate(this, innerHandler, nameof(InternalClient));
- }
InnerHandler = innerHandler;
if (Logging.IsEnabled)
- {
Logging.Associate(this, transportSettings, nameof(InternalClient));
- }
-
- _transportSettings = transportSettings;
_fileUploadHttpTransportHandler = new HttpTransportHandler(pipelineContext, IotHubConnectionString, options.FileUploadTransportSettings);
if (Logging.IsEnabled)
- {
Logging.Exit(this, transportSettings, pipelineBuilder, nameof(InternalClient) + "_ctor");
- }
}
///
@@ -224,7 +217,6 @@ public int DiagnosticSamplingPercentage
///
/// Gets or sets the timeout used in the operation retries.
///
- // Codes_SRS_DEVICECLIENT_28_002: [This property shall be defaulted to 240000 (4 minutes).]
public uint OperationTimeoutInMilliseconds { get; set; } = DeviceClient.DefaultOperationTimeoutInMilliseconds;
///
@@ -242,8 +234,6 @@ public string ProductInfo
///
/// Stores the retry strategy used in the operation retries.
///
- // Codes_SRS_DEVICECLIENT_28_001: [This property shall be defaulted to the exponential retry strategy with back-off
- // parameters for calculating delay in between retries.]
[Obsolete("This method has been deprecated. Please use Microsoft.Azure.Devices.Client.SetRetryPolicy(IRetryPolicy retryPolicy) instead.")]
public RetryPolicyType RetryPolicy { get; set; }
@@ -257,8 +247,6 @@ public string ProductInfo
/// Sets the retry policy used in the operation retries.
///
/// The retry policy. The default is new ExponentialBackoff(int.MaxValue, TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(10), TimeSpan.FromMilliseconds(100));
- // Codes_SRS_DEVICECLIENT_28_001: [This property shall be defaulted to the exponential retry strategy with back-off
- // parameters for calculating delay in between retries.]
public void SetRetryPolicy(IRetryPolicy retryPolicy)
{
RetryDelegatingHandler retryDelegatingHandler = GetDelegateHandler();
@@ -297,7 +285,6 @@ public async Task OpenAsync()
{
try
{
- // Codes_SRS_DEVICECLIENT_28_007: [ The asynchronous operation shall retry until time specified in OperationTimeoutInMilliseconds property expire or unrecoverable(authentication, quota exceed) error occurs.]
using CancellationTokenSource cts = CancellationTokenSourceFactory();
await OpenAsync(cts.Token).ConfigureAwait(false);
}
@@ -311,7 +298,7 @@ public async Task OpenAsync()
///
/// Explicitly open the InternalClient instance.
///
- /// A cancellation token that can be used by other objects or threads to receive notice of cancellation.
+ /// A token to cancel the operation.
public Task OpenAsync(CancellationToken cancellationToken)
{
try
@@ -346,6 +333,7 @@ public async Task CloseAsync()
///
/// Close the InternalClient instance
///
+ /// A token to cancel the operation.
public Task CloseAsync(CancellationToken cancellationToken)
{
try
@@ -366,8 +354,6 @@ public Task CloseAsync(CancellationToken cancellationToken)
/// The name of the method to associate with the delegate.
public void SetConnectionStatusChangesHandler(ConnectionStatusChangesHandler statusChangesHandler)
{
- // codes_SRS_DEVICECLIENT_28_025: [** `SetConnectionStatusChangesHandler` shall set connectionStatusChangesHandler **]**
- // codes_SRS_DEVICECLIENT_28_026: [** `SetConnectionStatusChangesHandler` shall unset connectionStatusChangesHandler if `statusChangesHandler` is null **]**
if (Logging.IsEnabled)
{
Logging.Info(this, statusChangesHandler, nameof(SetConnectionStatusChangesHandler));
@@ -384,9 +370,7 @@ internal void OnConnectionStatusChanged(ConnectionStatus status, ConnectionStatu
try
{
if (Logging.IsEnabled)
- {
Logging.Enter(this, status, reason, nameof(OnConnectionStatusChanged));
- }
if (_connectionStatusChangesHandler != null
&& (_lastConnectionStatus != status
@@ -414,7 +398,6 @@ public async Task CompleteAsync(string lockToken)
{
try
{
- // Codes_SRS_DEVICECLIENT_28_013: [The asynchronous operation shall retry until time specified in OperationTimeoutInMilliseconds property expire or unrecoverable error(authentication, quota exceed) occurs.]
using CancellationTokenSource cts = CancellationTokenSourceFactory();
await CompleteAsync(lockToken, cts.Token).ConfigureAwait(false);
}
@@ -429,11 +412,10 @@ public async Task CompleteAsync(string lockToken)
/// Deletes a received message from the device queue
///
///
- /// A cancellation token that can be used by other objects or threads to receive notice of cancellation.
+ /// A token to cancel the operation.
/// The lock identifier for the previously received message
public Task CompleteAsync(string lockToken, CancellationToken cancellationToken)
{
- // Codes_SRS_DEVICECLIENT_28_013: [The asynchronous operation shall retry until time specified in OperationTimeoutInMilliseconds property expire or unrecoverable error(authentication, quota exceed) occurs.]
if (string.IsNullOrEmpty(lockToken))
{
throw new ArgumentNullException(nameof(lockToken));
@@ -461,7 +443,6 @@ public Task CompleteAsync(Message message)
throw new ArgumentNullException(nameof(message));
}
- // Codes_SRS_DEVICECLIENT_28_015: [The asynchronous operation shall retry until time specified in OperationTimeoutInMilliseconds property expire or unrecoverable error(authentication, quota exceed) occurs.]
return CompleteAsync(message.LockToken);
}
@@ -469,7 +450,7 @@ public Task CompleteAsync(Message message)
/// Deletes a received message from the device queue
///
/// The message to complete
- /// A cancellation token that can be used by other objects or threads to receive notice of cancellation.
+ /// A token to cancel the operation.
/// The previously received message
public Task CompleteAsync(Message message, CancellationToken cancellationToken)
{
@@ -506,7 +487,6 @@ public async Task AbandonAsync(string lockToken)
// Exception adaptation for non-CancellationToken public API.
throw new TimeoutException("The operation timed out.", ex);
}
- // Codes_SRS_DEVICECLIENT_28_013: [The asynchronous operation shall retry until time specified in OperationTimeoutInMilliseconds property expire or unrecoverable error(authentication, quota exceed) occurs.]
}
///
@@ -573,7 +553,6 @@ public async Task RejectAsync(string lockToken)
{
try
{
- // Codes_SRS_DEVICECLIENT_28_013: [The asynchronous operation shall retry until time specified in OperationTimeoutInMilliseconds property expire or unrecoverable error(authentication, quota exceed) occurs.]
using CancellationTokenSource cts = CancellationTokenSourceFactory();
await RejectAsync(lockToken, cts.Token).ConfigureAwait(false);
}
@@ -647,7 +626,6 @@ public async Task SendEventAsync(Message message)
{
try
{
- // Codes_SRS_DEVICECLIENT_28_013: [The asynchronous operation shall retry until time specified in OperationTimeoutInMilliseconds property expire or unrecoverable error(authentication, quota exceed) occurs.]
using CancellationTokenSource cts = CancellationTokenSourceFactory();
await SendEventAsync(message, cts.Token).ConfigureAwait(false);
}
@@ -695,7 +673,6 @@ public async Task SendEventBatchAsync(IEnumerable messages)
{
try
{
- // Codes_SRS_DEVICECLIENT_28_013: [The asynchronous operation shall retry until time specified in OperationTimeoutInMilliseconds property expire or unrecoverable error(authentication, quota exceed) occurs.]
using CancellationTokenSource cts = CancellationTokenSourceFactory();
await SendEventBatchAsync(messages, cts.Token).ConfigureAwait(false);
}
@@ -752,7 +729,6 @@ public async Task SetMethodHandlerAsync(string methodName, MethodCallback method
{
try
{
- // Codes_SRS_DEVICECLIENT_28_013: [The asynchronous operation shall retry until time specified in OperationTimeoutInMilliseconds property expire or unrecoverable error(authentication, quota exceed) occurs.]
using CancellationTokenSource cts = CancellationTokenSourceFactory();
await SetMethodHandlerAsync(methodName, methodHandler, userContext, cts.Token).ConfigureAwait(false);
}
@@ -830,7 +806,6 @@ public async Task SetMethodDefaultHandlerAsync(MethodCallback methodHandler, obj
// Exception adaptation for non-CancellationToken public API.
throw new TimeoutException("The operation timed out.", ex);
}
- // Codes_SRS_DEVICECLIENT_28_013: [The asynchronous operation shall retry until time specified in OperationTimeoutInMilliseconds property expire or unrecoverable error(authentication, quota exceed) occurs.]
}
///
@@ -857,7 +832,6 @@ public async Task SetMethodDefaultHandlerAsync(MethodCallback methodHandler, obj
{
await HandleMethodEnableAsync(cancellationToken).ConfigureAwait(false);
- // codes_SRS_DEVICECLIENT_24_001: [ If the default callback has already been set, it is replaced with the new callback. ]
_deviceDefaultMethodCallback = new Tuple(methodHandler, userContext);
}
else
@@ -926,7 +900,6 @@ internal async Task OnMethodCalledAsync(MethodRequestInternal methodRequestInter
Logging.Enter(this, methodRequestInternal?.Name, methodRequestInternal, nameof(OnMethodCalledAsync));
}
- // codes_SRS_DEVICECLIENT_10_012: [ If the given methodRequestInternal argument is null, fail silently ]
if (methodRequestInternal == null)
{
return;
@@ -951,7 +924,6 @@ internal async Task OnMethodCalledAsync(MethodRequestInternal methodRequestInter
Logging.Error(this, ex, nameof(OnMethodCalledAsync));
}
- // codes_SRS_DEVICECLIENT_28_020: [ If the given methodRequestInternal data is not valid json, respond with status code 400 (BAD REQUEST) ]
methodResponseInternal = new MethodResponseInternal(methodRequestInternal.RequestId, (int)MethodResponseStatusCode.BadRequest);
await SendMethodResponseAsync(methodResponseInternal, methodRequestInternal.CancellationToken).ConfigureAwait(false);
@@ -978,19 +950,14 @@ internal async Task OnMethodCalledAsync(MethodRequestInternal methodRequestInter
if (callbackContextPair == null)
{
- // codes_SRS_DEVICECLIENT_10_013: [ If the given method does not have an associated delegate and no default delegate was registered, respond with status code 501 (METHOD NOT IMPLEMENTED) ]
methodResponseInternal = new MethodResponseInternal(methodRequestInternal.RequestId, (int)MethodResponseStatusCode.MethodNotImplemented);
}
else
{
try
{
- // codes_SRS_DEVICECLIENT_10_011: [ The OnMethodCalled shall invoke the specified delegate. ]
- // codes_SRS_DEVICECLIENT_24_002: [ The OnMethodCalled shall invoke the default delegate if there is no specified delegate for that method. ]
MethodResponse rv = await callbackContextPair.Item1(new MethodRequest(methodRequestInternal.Name, requestData), callbackContextPair.Item2).ConfigureAwait(false);
- // codes_SRS_DEVICECLIENT_03_012: [If the MethodResponse does not contain result, the MethodResponseInternal constructor shall be invoked with no results.]
- // codes_SRS_DEVICECLIENT_03_013: [Otherwise, the MethodResponseInternal constructor shall be invoked with the result supplied.]
methodResponseInternal = rv.Result == null
? new MethodResponseInternal(methodRequestInternal.RequestId, rv.Status)
: new MethodResponseInternal(rv.Result, methodRequestInternal.RequestId, rv.Status);
@@ -1002,7 +969,6 @@ internal async Task OnMethodCalledAsync(MethodRequestInternal methodRequestInter
Logging.Error(this, ex, nameof(OnMethodCalledAsync));
}
- // codes_SRS_DEVICECLIENT_28_021: [ If the MethodResponse from the MethodHandler is not valid json, respond with status code 500 (USER CODE EXCEPTION) ]
methodResponseInternal = new MethodResponseInternal(methodRequestInternal.RequestId, (int)MethodResponseStatusCode.UserCodeException);
}
}
@@ -1061,7 +1027,6 @@ public async Task SetDesiredPropertyUpdateCallbackAsync(DesiredPropertyUpdateCal
{
try
{
- // Codes_SRS_DEVICECLIENT_28_013: [The asynchronous operation shall retry until time specified in OperationTimeoutInMilliseconds property expire or unrecoverable error(authentication, quota exceed) occurs.]
using CancellationTokenSource cts = CancellationTokenSourceFactory();
await SetDesiredPropertyUpdateCallbackAsync(callback, userContext, cts.Token).ConfigureAwait(false);
}
@@ -1085,13 +1050,8 @@ public async Task SetDesiredPropertyUpdateCallbackAsync(DesiredPropertyUpdateCal
/// A cancellation token that can be used by other objects or threads to receive notice of cancellation.
public async Task SetDesiredPropertyUpdateCallbackAsync(DesiredPropertyUpdateCallback callback, object userContext, CancellationToken cancellationToken)
{
- // Codes_SRS_DEVICECLIENT_18_003: `SetDesiredPropertyUpdateCallbackAsync` shall call the transport to register for PATCHes on it's first call.
- // Codes_SRS_DEVICECLIENT_18_004: `SetDesiredPropertyUpdateCallbackAsync` shall not call the transport to register for PATCHes on subsequent calls
-
if (Logging.IsEnabled)
- {
Logging.Enter(this, callback, userContext, nameof(SetDesiredPropertyUpdateCallbackAsync));
- }
// Wait to acquire the _twinSemaphore. This ensures that concurrently invoked SetDesiredPropertyUpdateCallbackAsync calls are invoked in a thread-safe manner.
await _twinDesiredPropertySemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
@@ -1151,7 +1111,6 @@ public async Task GetTwinAsync()
{
try
{
- // Codes_SRS_DEVICECLIENT_28_013: [The asynchronous operation shall retry until time specified in OperationTimeoutInMilliseconds property expire or unrecoverable error(authentication, quota exceed) occurs.]
using CancellationTokenSource cts = CancellationTokenSourceFactory();
return await GetTwinAsync(cts.Token).ConfigureAwait(false);
}
@@ -1189,7 +1148,6 @@ public async Task UpdateReportedPropertiesAsync(TwinCollection reportedPropertie
{
try
{
- // Codes_SRS_DEVICECLIENT_28_013: [The asynchronous operation shall retry until time specified in OperationTimeoutInMilliseconds property expire or unrecoverable error(authentication, quota exceed) occurs.]
using CancellationTokenSource cts = CancellationTokenSourceFactory();
await UpdateReportedPropertiesAsync(reportedProperties, cts.Token).ConfigureAwait(false);
}
@@ -1225,7 +1183,6 @@ public Task UpdateReportedPropertiesAsync(TwinCollection reportedProperties, Can
}
}
- // Codes_SRS_DEVICECLIENT_18_005: When a patch is received from the service, the `callback` shall be called.
internal void OnReportedStatePatchReceived(TwinCollection patch)
{
if (_desiredPropertyUpdateCallback == null)
@@ -1251,7 +1208,6 @@ public async Task ReceiveAsync()
{
try
{
- // Codes_SRS_DEVICECLIENT_28_011: [The asynchronous operation shall retry until time specified in OperationTimeoutInMilliseconds property expire or unrecoverable (authentication, quota exceed) error occurs.]
using CancellationTokenSource cts = CancellationTokenSourceFactory();
return await ReceiveAsync(cts.Token).ConfigureAwait(false);
}
@@ -1397,9 +1353,7 @@ private Task DisableReceiveMessageAsync(CancellationToken cancellationToken)
private async Task OnDeviceMessageReceivedAsync(Message message)
{
if (Logging.IsEnabled)
- {
Logging.Enter(this, message, nameof(OnDeviceMessageReceivedAsync));
- }
if (message == null)
{
@@ -1426,9 +1380,7 @@ private async Task OnDeviceMessageReceivedAsync(Message message)
}
if (Logging.IsEnabled)
- {
Logging.Exit(this, message, nameof(OnDeviceMessageReceivedAsync));
- }
}
internal Task GetFileUploadSasUriAsync(FileUploadSasUriRequest request, CancellationToken cancellationToken = default)
@@ -1468,9 +1420,7 @@ public Task UploadToBlobAsync(string blobName, Stream source, CancellationToken
try
{
if (Logging.IsEnabled)
- {
Logging.Enter(this, blobName, source, nameof(UploadToBlobAsync));
- }
if (string.IsNullOrEmpty(blobName))
{
@@ -1489,8 +1439,7 @@ public Task UploadToBlobAsync(string blobName, Stream source, CancellationToken
throw Fx.Exception.Argument(nameof(blobName), "Path segment count cannot exceed 254");
}
- return _fileUploadHttpTransportHandler
- .UploadToBlobAsync(blobName, source, cancellationToken);
+ return _fileUploadHttpTransportHandler.UploadToBlobAsync(blobName, source, cancellationToken);
}
catch (IotHubCommunicationException ex) when (ex.InnerException is OperationCanceledException)
{
@@ -1500,9 +1449,7 @@ public Task UploadToBlobAsync(string blobName, Stream source, CancellationToken
finally
{
if (Logging.IsEnabled)
- {
Logging.Exit(this, blobName, nameof(UploadToBlobAsync));
- }
}
}
@@ -1520,7 +1467,6 @@ public async Task SendEventAsync(string outputName, Message message)
{
try
{
- // Codes_SRS_DEVICECLIENT_28_013: [The asynchronous operation shall retry until time specified in OperationTimeoutInMilliseconds property expire or unrecoverable error(authentication, quota exceed) occurs.]
using CancellationTokenSource cts = CancellationTokenSourceFactory();
await SendEventAsync(outputName, message, cts.Token).ConfigureAwait(false);
}
@@ -1543,36 +1489,28 @@ public Task SendEventAsync(string outputName, Message message, CancellationToken
try
{
if (Logging.IsEnabled)
- {
Logging.Enter(this, outputName, message, nameof(SendEventAsync));
- }
ValidateModuleTransportHandler("SendEventAsync for a named output");
- // Codes_SRS_DEVICECLIENT_10_012: [If `outputName` is `null` or empty, an `ArgumentNullException` shall be thrown.]
if (string.IsNullOrWhiteSpace(outputName))
{
throw new ArgumentNullException(nameof(outputName));
}
- // Codes_SRS_DEVICECLIENT_10_013: [If `message` is `null` or empty, an `ArgumentNullException` shall be thrown.]
if (message == null)
{
throw new ArgumentNullException(nameof(message));
}
- // Codes_SRS_DEVICECLIENT_10_015: [The `output` property of a given `message` shall be assigned the value `outputName` before submitting each request to the transport layer.]
message.SystemProperties.Add(MessageSystemPropertyNames.OutputName, outputName);
- // Codes_SRS_DEVICECLIENT_10_011: [The `SendEventAsync` operation shall retry sending `message` until the `BaseClient::RetryStrategy` timespan expires or unrecoverable error(authentication or quota exceed) occurs.]
return InnerHandler.SendEventAsync(message, cancellationToken);
}
finally
{
if (Logging.IsEnabled)
- {
Logging.Exit(this, outputName, message, nameof(SendEventAsync));
- }
}
}
@@ -1586,7 +1524,6 @@ public async Task SendEventBatchAsync(string outputName, IEnumerable me
{
try
{
- // Codes_SRS_DEVICECLIENT_28_013: [The asynchronous operation shall retry until time specified in OperationTimeoutInMilliseconds property expire or unrecoverable error(authentication, quota exceed) occurs.]
using CancellationTokenSource cts = CancellationTokenSourceFactory();
await SendEventBatchAsync(outputName, messages, cts.Token).ConfigureAwait(false);
}
@@ -1609,37 +1546,29 @@ public Task SendEventBatchAsync(string outputName, IEnumerable messages
try
{
if (Logging.IsEnabled)
- {
Logging.Enter(this, outputName, messages, nameof(SendEventBatchAsync));
- }
ValidateModuleTransportHandler("SendEventBatchAsync for a named output");
- // Codes_SRS_DEVICECLIENT_10_012: [If `outputName` is `null` or empty, an `ArgumentNullException` shall be thrown.]
if (string.IsNullOrWhiteSpace(outputName))
{
throw new ArgumentNullException(nameof(outputName));
}
var messagesList = messages?.ToList();
- // Codes_SRS_DEVICECLIENT_10_013: [If `message` is `null` or empty, an `ArgumentNullException` shall be thrown]
if (messagesList == null || messagesList.Count == 0)
{
throw new ArgumentNullException(nameof(messages));
}
- // Codes_SRS_DEVICECLIENT_10_015: [The `module-output` property of a given `message` shall be assigned the value `outputName` before submitting each request to the transport layer.]
messagesList.ForEach(m => m.SystemProperties.Add(MessageSystemPropertyNames.OutputName, outputName));
- // Codes_SRS_DEVICECLIENT_10_014: [The `SendEventBachAsync` operation shall retry sending `messages` until the `BaseClient::RetryStrategy` timespan expires or unrecoverable error(authentication or quota exceed) occurs.]
return InnerHandler.SendEventAsync(messagesList, cancellationToken);
}
finally
{
if (Logging.IsEnabled)
- {
Logging.Exit(this, outputName, messages, nameof(SendEventBatchAsync));
- }
}
}
@@ -1657,7 +1586,6 @@ public async Task SetInputMessageHandlerAsync(string inputName, MessageHandler m
{
try
{
- // Codes_SRS_DEVICECLIENT_28_013: [The asynchronous operation shall retry until time specified in OperationTimeoutInMilliseconds property expire or unrecoverable error(authentication, quota exceed) occurs.]
using CancellationTokenSource cts = CancellationTokenSourceFactory();
await SetInputMessageHandlerAsync(inputName, messageHandler, userContext, isAnEdgeModule, cts.Token).ConfigureAwait(false);
}
@@ -1682,9 +1610,7 @@ public async Task SetInputMessageHandlerAsync(string inputName, MessageHandler m
public async Task SetInputMessageHandlerAsync(string inputName, MessageHandler messageHandler, object userContext, bool isAnEdgeModule, CancellationToken cancellationToken)
{
if (Logging.IsEnabled)
- {
Logging.Enter(this, inputName, messageHandler, userContext, nameof(SetInputMessageHandlerAsync));
- }
ValidateModuleTransportHandler("SetInputMessageHandlerAsync for a named output");
@@ -1698,7 +1624,6 @@ public async Task SetInputMessageHandlerAsync(string inputName, MessageHandler m
// When using a device module we need to enable the 'deviceBound' message link
await EnableEventReceiveAsync(isAnEdgeModule, cancellationToken).ConfigureAwait(false);
- // codes_SRS_DEVICECLIENT_33_005: [ It shall lazy-initialize the receiveEventEndpoints property. ]
if (_receiveEventEndpoints == null)
{
_receiveEventEndpoints = new Dictionary>();
@@ -1717,7 +1642,6 @@ public async Task SetInputMessageHandlerAsync(string inputName, MessageHandler m
}
}
- // codes_SRS_DEVICECLIENT_33_004: [ It shall call DisableEventReceiveAsync when the last delegate has been removed. ]
await DisableEventReceiveAsync(isAnEdgeModule, cancellationToken).ConfigureAwait(false);
}
}
@@ -1726,9 +1650,7 @@ public async Task SetInputMessageHandlerAsync(string inputName, MessageHandler m
_moduleReceiveMessageSemaphore.Release();
if (Logging.IsEnabled)
- {
Logging.Exit(this, inputName, messageHandler, userContext, nameof(SetInputMessageHandlerAsync));
- }
}
}
@@ -1746,7 +1668,6 @@ public async Task SetMessageHandlerAsync(MessageHandler messageHandler, object u
{
try
{
- // Codes_SRS_DEVICECLIENT_28_013: [The asynchronous operation shall retry until time specified in OperationTimeoutInMilliseconds property expire or unrecoverable error(authentication, quota exceed) occurs.]
using CancellationTokenSource cts = CancellationTokenSourceFactory();
await SetMessageHandlerAsync(messageHandler, userContext, isAnEdgeModule, cts.Token).ConfigureAwait(false);
}
@@ -1771,9 +1692,7 @@ public async Task SetMessageHandlerAsync(MessageHandler messageHandler, object u
public async Task SetMessageHandlerAsync(MessageHandler messageHandler, object userContext, bool isAnEdgeModule, CancellationToken cancellationToken)
{
if (Logging.IsEnabled)
- {
Logging.Enter(this, messageHandler, userContext, nameof(SetMessageHandlerAsync));
- }
cancellationToken.ThrowIfCancellationRequested();
await _moduleReceiveMessageSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
@@ -1782,14 +1701,12 @@ public async Task SetMessageHandlerAsync(MessageHandler messageHandler, object u
{
if (messageHandler != null)
{
- // codes_SRS_DEVICECLIENT_33_003: [ It shall EnableEventReceiveAsync when called for the first time. ]
await EnableEventReceiveAsync(isAnEdgeModule, cancellationToken).ConfigureAwait(false);
_defaultEventCallback = new Tuple(messageHandler, userContext);
}
else
{
_defaultEventCallback = null;
- // codes_SRS_DEVICECLIENT_33_004: [ It shall DisableEventReceiveAsync when the last delegate has been removed. ]
await DisableEventReceiveAsync(isAnEdgeModule, cancellationToken).ConfigureAwait(false);
}
}
@@ -1798,9 +1715,7 @@ public async Task SetMessageHandlerAsync(MessageHandler messageHandler, object u
_moduleReceiveMessageSemaphore.Release();
if (Logging.IsEnabled)
- {
Logging.Exit(this, messageHandler, userContext, nameof(SetMessageHandlerAsync));
- }
}
}
@@ -1812,11 +1727,8 @@ public async Task SetMessageHandlerAsync(MessageHandler messageHandler, object u
internal async Task OnModuleEventMessageReceivedAsync(string input, Message message)
{
if (Logging.IsEnabled)
- {
Logging.Enter(this, input, message, nameof(OnModuleEventMessageReceivedAsync));
- }
- // codes_SRS_DEVICECLIENT_33_001: [ If the given eventMessageInternal argument is null, fail silently ]
if (message == null)
{
return;
@@ -1828,7 +1740,6 @@ internal async Task OnModuleEventMessageReceivedAsync(string input, Message mess
await _moduleReceiveMessageSemaphore.WaitAsync().ConfigureAwait(false);
try
{
- // codes_SRS_DEVICECLIENT_33_006: [ The OnReceiveEventMessageCalled shall get the default delegate if a delegate has not been assigned. ]
if (_receiveEventEndpoints == null ||
string.IsNullOrWhiteSpace(input) ||
!_receiveEventEndpoints.TryGetValue(input, out callback))
@@ -1841,12 +1752,9 @@ internal async Task OnModuleEventMessageReceivedAsync(string input, Message mess
_moduleReceiveMessageSemaphore.Release();
}
- // codes_SRS_DEVICECLIENT_33_002: [ The OnReceiveEventMessageCalled shall invoke the specified delegate. ]
MessageResponse response = await (callback?.Item1?.Invoke(message, callback.Item2) ?? Task.FromResult(MessageResponse.Completed)).ConfigureAwait(false);
if (Logging.IsEnabled)
- {
Logging.Info(this, $"{nameof(MessageResponse)} = {response}", nameof(OnModuleEventMessageReceivedAsync));
- }
switch (response)
{
@@ -1865,9 +1773,7 @@ internal async Task OnModuleEventMessageReceivedAsync(string input, Message mess
finally
{
if (Logging.IsEnabled)
- {
Logging.Exit(this, input, message, nameof(OnModuleEventMessageReceivedAsync));
- }
}
}
diff --git a/iothub/device/src/IotHubConnectionString.Core.cs b/iothub/device/src/IotHubConnectionString.Core.cs
index 543ea47c5f..caeadbe722 100644
--- a/iothub/device/src/IotHubConnectionString.Core.cs
+++ b/iothub/device/src/IotHubConnectionString.Core.cs
@@ -12,7 +12,7 @@ internal sealed partial class IotHubConnectionString : IAuthorizationProvider
{
public AuthenticationWithTokenRefresh TokenRefresher { get; private set; }
- Task IAuthorizationProvider.GetPasswordAsync()
+ async Task IAuthorizationProvider.GetPasswordAsync()
{
try
{
@@ -24,9 +24,17 @@ Task IAuthorizationProvider.GetPasswordAsync()
|| TokenRefresher != null,
"The token refresher and the shared access signature can't both be null");
- return !string.IsNullOrWhiteSpace(SharedAccessSignature)
- ? Task.FromResult(SharedAccessSignature)
- : TokenRefresher?.GetTokenAsync(Audience);
+ if (!string.IsNullOrWhiteSpace(SharedAccessSignature))
+ {
+ return SharedAccessSignature;
+ }
+
+ if (TokenRefresher != null)
+ {
+ return await TokenRefresher.GetTokenAsync(Audience);
+ }
+
+ return null;
}
finally
{
diff --git a/iothub/device/src/IotHubConnectionString.cs b/iothub/device/src/IotHubConnectionString.cs
index b41bad43e6..daf1e632fd 100644
--- a/iothub/device/src/IotHubConnectionString.cs
+++ b/iothub/device/src/IotHubConnectionString.cs
@@ -34,16 +34,12 @@ public IotHubConnectionString(IotHubConnectionStringBuilder builder)
AmqpEndpoint = new UriBuilder(CommonConstants.AmqpsScheme, HostName, DefaultSecurePort).Uri;
- if (builder.AuthenticationMethod is AuthenticationWithTokenRefresh)
+ if (builder.AuthenticationMethod is AuthenticationWithTokenRefresh authWithTokenRefresh)
{
- TokenRefresher = (AuthenticationWithTokenRefresh)builder.AuthenticationMethod;
+ TokenRefresher = authWithTokenRefresh;
if (Logging.IsEnabled)
{
Logging.Info(this, $"{nameof(IAuthenticationMethod)} is {nameof(AuthenticationWithTokenRefresh)}: {Logging.IdOf(TokenRefresher)}");
- }
-
- if (Logging.IsEnabled)
- {
Logging.Associate(this, TokenRefresher, nameof(TokenRefresher));
}
@@ -53,29 +49,23 @@ public IotHubConnectionString(IotHubConnectionStringBuilder builder)
{
if (ModuleId.IsNullOrWhiteSpace())
{
- // Since the sdk creates the instance of disposable DeviceAuthenticationWithSakRefresh, the sdk needs to dispose it once the client is disposed.
+ // Since the SDK creates the instance of disposable DeviceAuthenticationWithSakRefresh, the SDK needs to dispose it once the client is disposed.
TokenRefresher = new DeviceAuthenticationWithSakRefresh(DeviceId, this, builder.SasTokenTimeToLive, builder.SasTokenRenewalBuffer, disposeWithClient: true);
if (Logging.IsEnabled)
- {
Logging.Info(this, $"{nameof(IAuthenticationMethod)} is {nameof(DeviceAuthenticationWithSakRefresh)}: {Logging.IdOf(TokenRefresher)}");
- }
}
else
{
- // Since the sdk creates the instance of disposable ModuleAuthenticationWithSakRefresh, the sdk needs to dispose it once the client is disposed.
+ // Since the SDK creates the instance of disposable ModuleAuthenticationWithSakRefresh, the SDK needs to dispose it once the client is disposed.
TokenRefresher = new ModuleAuthenticationWithSakRefresh(DeviceId, ModuleId, this, builder.SasTokenTimeToLive, builder.SasTokenRenewalBuffer, disposeWithClient: true);
if (Logging.IsEnabled)
- {
Logging.Info(this, $"{nameof(IAuthenticationMethod)} is {nameof(ModuleAuthenticationWithSakRefresh)}: {Logging.IdOf(TokenRefresher)}");
- }
}
if (Logging.IsEnabled)
- {
Logging.Associate(this, TokenRefresher, nameof(TokenRefresher));
- }
Debug.Assert(TokenRefresher != null);
}
diff --git a/iothub/device/src/IotHubConnectionStringBuilder.cs b/iothub/device/src/IotHubConnectionStringBuilder.cs
index 181cd642f6..8fd1a34917 100644
--- a/iothub/device/src/IotHubConnectionStringBuilder.cs
+++ b/iothub/device/src/IotHubConnectionStringBuilder.cs
@@ -116,8 +116,8 @@ internal static IotHubConnectionStringBuilder CreateWithIAuthenticationOverride(
if (authenticationMethod == null)
{
iotHubConnectionStringBuilder.Parse(iotHubConnectionString);
- iotHubConnectionStringBuilder.AuthenticationMethod =
- AuthenticationMethodFactory.GetAuthenticationMethod(iotHubConnectionStringBuilder);
+ iotHubConnectionStringBuilder.AuthenticationMethod = AuthenticationMethodFactory.GetAuthenticationMethod(
+ iotHubConnectionStringBuilder);
}
else
{
diff --git a/iothub/device/src/Transport/HttpClientHelper.cs b/iothub/device/src/Transport/HttpClientHelper.cs
index 363fb42841..08d41243c4 100644
--- a/iothub/device/src/Transport/HttpClientHelper.cs
+++ b/iothub/device/src/Transport/HttpClientHelper.cs
@@ -53,13 +53,11 @@ public HttpClientHelper(
HttpClientHandler httpClientHandler,
ProductInfo productInfo,
IWebProxy proxy,
- bool isClientPrimaryTransportHandler = false
- )
+ bool isClientPrimaryTransportHandler = false)
{
_baseAddress = baseAddress;
_authenticationHeaderProvider = authenticationHeaderProvider;
- _defaultErrorMapping =
- new ReadOnlyDictionary>>(defaultErrorMapping);
+ _defaultErrorMapping = new ReadOnlyDictionary>>(defaultErrorMapping);
#if NET451
TlsVersions.Instance.SetLegacyAcceptableVersions();
@@ -385,17 +383,17 @@ public Task DeleteAsync(
CancellationToken cancellationToken) where T : IETagHolder
{
return ExecuteAsync(
- HttpMethod.Delete,
- new Uri(_baseAddress, requestUri),
- (requestMsg, token) =>
- {
- InsertEtag(requestMsg, entity);
- AddCustomHeaders(requestMsg, customHeaders);
- return TaskHelpers.CompletedTask;
- },
- null,
- errorMappingOverrides,
- cancellationToken);
+ HttpMethod.Delete,
+ new Uri(_baseAddress, requestUri),
+ (requestMsg, token) =>
+ {
+ InsertEtag(requestMsg, entity);
+ AddCustomHeaders(requestMsg, customHeaders);
+ return TaskHelpers.CompletedTask;
+ },
+ null,
+ errorMappingOverrides,
+ cancellationToken);
}
private Task ExecuteAsync(
@@ -434,7 +432,10 @@ private async Task ExecuteAsync(
if (!_usingX509ClientCert)
{
string authHeader = await _authenticationHeaderProvider.GetPasswordAsync().ConfigureAwait(false);
- msg.Headers.Add(HttpRequestHeader.Authorization.ToString(), authHeader);
+ if (!string.IsNullOrWhiteSpace(authHeader))
+ {
+ msg.Headers.Add(HttpRequestHeader.Authorization.ToString(), authHeader);
+ }
}
msg.Headers.UserAgent.ParseAdd(_productInfo.ToString(UserAgentFormats.Http));