public async Task DeviceClient_TokenConnectionDoubleRelease_Ok() { TestDevice testDevice = await TestDevice.GetTestDeviceAsync(DevicePrefix).ConfigureAwait(false); string deviceConnectionString = testDevice.ConnectionString; var config = new Configuration.IoTHub.DeviceConnectionStringParser(deviceConnectionString); string iotHub = config.IoTHub; string deviceId = config.DeviceID; string key = config.SharedAccessKey; SharedAccessSignatureBuilder builder = new SharedAccessSignatureBuilder() { Key = key, TimeToLive = new TimeSpan(0, 10, 0), Target = $"{iotHub}/devices/{WebUtility.UrlEncode(deviceId)}", }; DeviceAuthenticationWithToken auth = new DeviceAuthenticationWithToken(deviceId, builder.ToSignature()); using (DeviceClient deviceClient = DeviceClient.Create(iotHub, auth, Client.TransportType.Amqp_Tcp_Only)) { _log.WriteLine($"Created {nameof(DeviceClient)} ID={TestLogging.IdOf(deviceClient)}"); Console.WriteLine("DeviceClient OpenAsync."); await deviceClient.OpenAsync().ConfigureAwait(false); Console.WriteLine("DeviceClient SendEventAsync."); await deviceClient.SendEventAsync(new Client.Message(Encoding.UTF8.GetBytes("TestMessage"))).ConfigureAwait(false); Console.WriteLine("DeviceClient CloseAsync."); await deviceClient.CloseAsync().ConfigureAwait(false); // First release } // Second release }
private async Task ModuleClient_Gives_ConnectionStatus_DeviceDisabled_Base( Client.TransportType protocol, Func <RegistryManager, string, Task> registryManagerOperation) { AmqpTransportSettings amqpTransportSettings = new AmqpTransportSettings(protocol); ITransportSettings[] transportSettings = new ITransportSettings[] { amqpTransportSettings }; TestModule testModule = await TestModule.GetTestModuleAsync(DevicePrefix + $"_{Guid.NewGuid()}", ModulePrefix).ConfigureAwait(false); ConnectionStatus? status = null; ConnectionStatusChangeReason?statusChangeReason = null; int deviceDisabledReceivedCount = 0; ConnectionStatusChangesHandler statusChangeHandler = (s, r) => { if (r == ConnectionStatusChangeReason.Device_Disabled) { status = s; statusChangeReason = r; deviceDisabledReceivedCount++; } }; using (ModuleClient moduleClient = ModuleClient.CreateFromConnectionString(testModule.ConnectionString, transportSettings)) { moduleClient.SetConnectionStatusChangesHandler(statusChangeHandler); _log.WriteLine($"Created {nameof(DeviceClient)} ID={TestLogging.IdOf(moduleClient)}"); Console.WriteLine("ModuleClient OpenAsync."); await moduleClient.OpenAsync().ConfigureAwait(false); // Receiving the module twin should succeed right now. Console.WriteLine("ModuleClient GetTwinAsync."); var twin = await moduleClient.GetTwinAsync().ConfigureAwait(false); Assert.IsNotNull(twin); // Delete/disable the device in IoT Hub. using (RegistryManager registryManager = RegistryManager.CreateFromConnectionString(Configuration.IoTHub.ConnectionString)) { await registryManagerOperation(registryManager, testModule.DeviceId).ConfigureAwait(false); } // Artificial sleep waiting for the connection status change handler to get triggered. int sleepCount = 50; for (int i = 0; i < sleepCount; i++) { await Task.Delay(TimeSpan.FromSeconds(10)).ConfigureAwait(false); if (deviceDisabledReceivedCount == 1) { break; } } Assert.AreEqual(1, deviceDisabledReceivedCount); Assert.AreEqual(ConnectionStatus.Disconnected, status); Assert.AreEqual(ConnectionStatusChangeReason.Device_Disabled, statusChangeReason); } }
private async Task DeviceClient_TokenIsRefreshed_Internal(Client.TransportType transport, int ttl = 20) { TestDevice testDevice = await TestDevice.GetTestDeviceAsync(DevicePrefix).ConfigureAwait(false); int buffer = 50; Device device = testDevice.Identity; SemaphoreSlim deviceDisconnected = new SemaphoreSlim(0); var refresher = new TestTokenRefresher( device.Id, device.Authentication.SymmetricKey.PrimaryKey, ttl, buffer, transport); using (DeviceClient deviceClient = DeviceClient.Create(testDevice.IoTHubHostName, refresher, transport)) { _log.WriteLine($"Created {nameof(DeviceClient)} ID={TestLogging.IdOf(deviceClient)}"); if (transport == Client.TransportType.Mqtt) { deviceClient.SetConnectionStatusChangesHandler((ConnectionStatus status, ConnectionStatusChangeReason reason) => { _log.WriteLine($"{nameof(ConnectionStatusChangesHandler)}: {status}; {reason}"); if (status == ConnectionStatus.Disconnected_Retrying || status == ConnectionStatus.Disconnected) { deviceDisconnected.Release(); } }); } var message = new Client.Message(Encoding.UTF8.GetBytes("Hello")); using (var cts = new CancellationTokenSource(TimeSpan.FromSeconds(ttl * 10))) { try { // Create the first Token. Console.WriteLine($"[{DateTime.UtcNow}] OpenAsync"); await deviceClient.OpenAsync(cts.Token).ConfigureAwait(false); Console.WriteLine($"[{DateTime.UtcNow}] SendEventAsync (1)"); await deviceClient.SendEventAsync(message, cts.Token).ConfigureAwait(false); await refresher.WaitForTokenRefreshAsync(cts.Token).ConfigureAwait(false); } catch (OperationCanceledException ex) { Assert.Fail($"{TestLogging.IdOf(deviceClient)} did not get the initial token. {ex}"); throw; } // Wait for the Token to expire. if (transport == Client.TransportType.Http1) { float waitTime = (float)ttl * ((float)buffer / 100) + 1; Console.WriteLine($"[{DateTime.UtcNow}] Waiting {waitTime} seconds."); await Task.Delay(TimeSpan.FromSeconds(waitTime)).ConfigureAwait(false); } else if (transport == Client.TransportType.Mqtt) { Console.WriteLine($"[{DateTime.UtcNow}] Waiting for device disconnect."); await deviceDisconnected.WaitAsync(cts.Token).ConfigureAwait(false); } try { Console.WriteLine($"[{DateTime.UtcNow}] SendEventAsync (2)"); await deviceClient.SendEventAsync(message, cts.Token).ConfigureAwait(false); await refresher.WaitForTokenRefreshAsync(cts.Token).ConfigureAwait(false); } catch (OperationCanceledException ex) { Assert.Fail($"{TestLogging.IdOf(deviceClient)} did not refresh token after {refresher.DetectedRefreshInterval}. {ex}"); throw; } // Ensure that the token was refreshed. Console.WriteLine($"[{DateTime.UtcNow}] Token was refreshed after {refresher.DetectedRefreshInterval} (ttl = {ttl} seconds)."); Assert.IsTrue( refresher.DetectedRefreshInterval.TotalSeconds < (float)ttl * (1 + (float)buffer / 100), // Wait for more than what we expect. $"Token was refreshed after {refresher.DetectedRefreshInterval} although ttl={ttl} seconds."); Console.WriteLine($"[{DateTime.UtcNow}] CloseAsync"); await deviceClient.CloseAsync().ConfigureAwait(false); } } }
public DeviceClient CreateDeviceClient(ITransportSettings[] transportSettings, ConnectionStringAuthScope authScope = ConnectionStringAuthScope.Device) { DeviceClient deviceClient = null; if (_authenticationMethod == null) { if (authScope == ConnectionStringAuthScope.Device) { deviceClient = DeviceClient.CreateFromConnectionString(ConnectionString, transportSettings); s_log.WriteLine($"{nameof(CreateDeviceClient)}: Created {nameof(DeviceClient)} {_device.Id} from device connection string: ID={TestLogging.IdOf(deviceClient)}"); } else { deviceClient = DeviceClient.CreateFromConnectionString(Configuration.IoTHub.ConnectionString, _device.Id, transportSettings); s_log.WriteLine($"{nameof(CreateDeviceClient)}: Created {nameof(DeviceClient)} {_device.Id} from IoTHub connection string: ID={TestLogging.IdOf(deviceClient)}"); } } else { deviceClient = DeviceClient.Create(IoTHubHostName, AuthenticationMethod, transportSettings); s_log.WriteLine($"{nameof(CreateDeviceClient)}: Created {nameof(DeviceClient)} {_device.Id} from IAuthenticationMethod: ID={TestLogging.IdOf(deviceClient)}"); } return(deviceClient); }
public DeviceClient CreateDeviceClient(Client.TransportType transport) { DeviceClient deviceClient = null; if (_authenticationMethod == null) { deviceClient = DeviceClient.CreateFromConnectionString(ConnectionString, transport); s_log.WriteLine($"{nameof(CreateDeviceClient)}: Created {nameof(DeviceClient)} {_device.Id} from connection string: {transport} ID={TestLogging.IdOf(deviceClient)}"); } else { deviceClient = DeviceClient.Create(IoTHubHostName, AuthenticationMethod, transport); s_log.WriteLine($"{nameof(CreateDeviceClient)}: Created {nameof(DeviceClient)} {_device.Id} from IAuthenticationMethod: {transport} ID={TestLogging.IdOf(deviceClient)}"); } return(deviceClient); }
async Task ModuleClient_Gives_ConnectionStatus_DeviceDisabled_Base( Client.TransportType protocol, Func <RegistryManager, string, Task> registryManagerOperation) { AmqpTransportSettings amqpTransportSettings = new AmqpTransportSettings(protocol); ITransportSettings[] transportSettings = new ITransportSettings[] { amqpTransportSettings }; TestModule testModule = await TestModule.GetTestModuleAsync(DevicePrefix + $"_{Guid.NewGuid()}", ModulePrefix).ConfigureAwait(false); ConnectionStatus? status = null; ConnectionStatusChangeReason?statusChangeReason = null; int deviceDisabledReceivedCount = 0; ConnectionStatusChangesHandler statusChangeHandler = (s, r) => { if (r == ConnectionStatusChangeReason.Device_Disabled) { status = s; statusChangeReason = r; deviceDisabledReceivedCount++; } }; using (ModuleClient moduleClient = ModuleClient.CreateFromConnectionString(testModule.ConnectionString, transportSettings)) { moduleClient.SetConnectionStatusChangesHandler(statusChangeHandler); _log.WriteLine($"Created {nameof(DeviceClient)} ID={TestLogging.IdOf(moduleClient)}"); Console.WriteLine("ModuleClient OpenAsync."); await moduleClient.OpenAsync().ConfigureAwait(false); // Receiving the module twin should succeed right now. Console.WriteLine("ModuleClient GetTwinAsync."); var twin = await moduleClient.GetTwinAsync().ConfigureAwait(false); Assert.IsNotNull(twin); // Delete the device in IoT Hub. using (RegistryManager registryManager = RegistryManager.CreateFromConnectionString(Configuration.IoTHub.ConnectionString)) { await registryManagerOperation(registryManager, testModule.DeviceId).ConfigureAwait(false); } // Periodically keep retrieving the device twin to keep connection alive. // The ConnectionStatusChangesHandler should be triggered when the connection is closed from IoT hub with an // exception thrown. int twinRetrievals = 50; for (int i = 0; i < twinRetrievals; i++) { try { await Task.Delay(TimeSpan.FromSeconds(10)).ConfigureAwait(false); if (deviceDisabledReceivedCount == 1) { // Call an API on the client again to trigger the ConnectionStatusChangesHandler once again with the // Device_Disabled status. // This currently does not work due to some issues with IoT hub allowing new connections even when the // device is deleted/disabled. Once that problem is investigated and fixed, we can re-enable this call // and test for multiple invocations of the ConnectionStatusChangeHandler. // await moduleClient.GetTwinAsync().ConfigureAwait(false); break; } } catch (IotHubException ex) { _log.WriteLine($"Exception occurred while retrieving module twin: {ex}"); Assert.IsInstanceOfType(ex.InnerException, typeof(DeviceNotFoundException)); } } Assert.AreEqual(1, deviceDisabledReceivedCount); Assert.AreEqual(ConnectionStatus.Disconnected, status); Assert.AreEqual(ConnectionStatusChangeReason.Device_Disabled, statusChangeReason); } }