private static async Task <FileNotification> VerifyFileNotification(FileNotificationReceiver <FileNotification> fileNotificationReceiver, string deviceId) { FileNotification fileNotification = null; Stopwatch sw = new Stopwatch(); sw.Start(); while (sw.Elapsed.TotalMinutes < 2) { // Receive the file notification from queue fileNotification = await fileNotificationReceiver.ReceiveAsync(TimeSpan.FromSeconds(20)).ConfigureAwait(false); if (fileNotification != null) { if (fileNotification.DeviceId == deviceId) { await fileNotificationReceiver.CompleteAsync(fileNotification).ConfigureAwait(false); break; } await fileNotificationReceiver.AbandonAsync(fileNotification).ConfigureAwait(false); fileNotification = null; } } sw.Stop(); return(fileNotification); }
/// <summary> /// Handle file notifications /// </summary> /// <param name="receiver"></param> /// <returns></returns> private async Task RunAsync(FileNotificationReceiver <FileNotification> receiver) { while (!_cts.IsCancellationRequested) { var notification = await receiver.ReceiveAsync(); if (notification == null) { continue; } // Parse content type from blob name var blobName = notification.BlobName; string contentType = null; var delim = blobName.IndexOf('/'); if (delim != -1) { // the first segment is the url encoded content type contentType = blobName.Substring(0, delim).UrlDecode(); blobName = blobName.Substring(delim + 1); } // Call handlers await Try.Async(() => Task.WhenAll(_handlers .Select(h => h.HandleAsync(notification.DeviceId, null, blobName, contentType, notification.BlobUri, notification.EnqueuedTimeUtc, _cts.Token)))); await receiver.CompleteAsync(notification); } }
public async Task StartListenAsync() { try { FileNotificationReceiver <FileNotification> fileNotificationReceiver = _serviceClient.GetFileNotificationReceiver(); while (true) { FileNotification fileNotification = null; try { fileNotification = await fileNotificationReceiver.ReceiveAsync(); if (fileNotification != null) { await SendToWebAppAsync(fileNotification); await fileNotificationReceiver.CompleteAsync(fileNotification); } } catch (Exception ex) { await fileNotificationReceiver.AbandonAsync(fileNotification); } } } catch (Exception ex) { Debug.WriteLine(ex.Message); } }
public static async Task InitAsync() { bool gained = await s_lock.WaitAsync(s_interval).ConfigureAwait(false); if (gained) { try { if (!s_receiving) { s_log.WriteLine("Initializing FileNotificationReceiver..."); ServiceClient serviceClient = ServiceClient.CreateFromConnectionString(Configuration.IoTHub.ConnectionString); s_fileNotificationReceiver = serviceClient.GetFileNotificationReceiver(); s_log.WriteLine("Receiving once to connect FileNotificationReceiver..."); await s_fileNotificationReceiver.ReceiveAsync(TimeSpan.FromSeconds(1)).ConfigureAwait(false); s_log.WriteLine("FileNotificationReceiver connected."); _ = StartReceivingLoopAsync().ConfigureAwait(false); s_receiving = true; } } finally { s_lock.Release(); } } }
async Task uploadFile(Client.TransportType transport, string filename, bool x509auth = false) { DeviceClient deviceClient; Tuple <string, string> deviceInfo; if (x509auth) { deviceInfo = TestUtil.CreateDeviceWithX509(DevicePrefix, hostName, registryManager); string certBase64 = Environment.GetEnvironmentVariable("IOTHUB_X509_PFX_CERTIFICATE"); Byte[] buff = Convert.FromBase64String(certBase64); var cert = new X509Certificate2(buff); var auth = new DeviceAuthenticationWithX509Certificate(deviceInfo.Item1, cert); deviceClient = DeviceClient.Create(deviceInfo.Item2, auth, transport); } else { deviceInfo = TestUtil.CreateDevice(DevicePrefix, hostName, registryManager); deviceClient = DeviceClient.CreateFromConnectionString(deviceInfo.Item2, transport); } using (FileStream fileStreamSource = new FileStream(filename, FileMode.Open, FileAccess.Read)) { await deviceClient.UploadToBlobAsync(filename, fileStreamSource); } ServiceClient serviceClient = ServiceClient.CreateFromConnectionString(hubConnectionString); FileNotificationReceiver <FileNotification> fileNotificationReceiver = serviceClient.GetFileNotificationReceiver(); FileNotification fileNotification; while (true) { // Receive the file notification from queue fileNotification = await fileNotificationReceiver.ReceiveAsync(TimeSpan.FromSeconds(20)); Assert.IsNotNull(fileNotification); await fileNotificationReceiver.CompleteAsync(fileNotification); if (deviceInfo.Item1 == fileNotification.DeviceId) { break; } } Assert.AreEqual(deviceInfo.Item1 + "/" + filename, fileNotification.BlobName, "Uploaded file name mismatch in notifications"); Assert.AreEqual(new FileInfo(filename).Length, fileNotification.BlobSizeInBytes, "Uploaded file size mismatch in notifications"); Assert.IsFalse(string.IsNullOrEmpty(fileNotification.BlobUri), "File notification blob uri is null or empty"); await deviceClient.CloseAsync(); await serviceClient.CloseAsync(); TestUtil.RemoveDevice(deviceInfo.Item1, registryManager); }
private async Task UploadFileDisconnectTransport( Client.TransportType transport, string filename, string faultType, string reason, int delayInSec, int durationInSec = 0, int retryDurationInMilliSec = FaultInjection.RecoveryTimeMilliseconds) { TestDevice testDevice = await TestDevice.GetTestDeviceAsync(DevicePrefix).ConfigureAwait(false); ServiceClient serviceClient = ServiceClient.CreateFromConnectionString(Configuration.IoTHub.ConnectionString); FileNotificationReceiver <FileNotification> notificationReceiver = serviceClient.GetFileNotificationReceiver(); DeviceClient deviceClient = DeviceClient.CreateFromConnectionString(testDevice.ConnectionString, transport); deviceClient.OperationTimeoutInMilliseconds = (uint)retryDurationInMilliSec; Task fileuploadTask; Task <FileNotification> verifyTask; using (FileStream fileStreamSource = new FileStream(filename, FileMode.Open, FileAccess.Read)) { verifyTask = VerifyFileNotification(notificationReceiver, testDevice.Id); fileuploadTask = deviceClient.UploadToBlobAsync(filename, fileStreamSource); try { await deviceClient.SendEventAsync(FaultInjection.ComposeErrorInjectionProperties(faultType, reason, delayInSec, durationInSec)).ConfigureAwait(false); } catch (Exception) { // catch and ignore exceptions resulted from error injection and continue to // check result of the file upload status } await Task.WhenAll(fileuploadTask, verifyTask).ConfigureAwait(false); } FileNotification fileNotification = await verifyTask.ConfigureAwait(false); Assert.IsNotNull(fileNotification, "FileNotification is not received."); Assert.AreEqual(testDevice.Id + "/" + filename, fileNotification.BlobName, "Uploaded file name mismatch in notifications"); Assert.AreEqual(new FileInfo(filename).Length, fileNotification.BlobSizeInBytes, "Uploaded file size mismatch in notifications"); Assert.IsFalse(string.IsNullOrEmpty(fileNotification.BlobUri), "File notification blob uri is null or empty"); await deviceClient.CloseAsync().ConfigureAwait(false); await serviceClient.CloseAsync().ConfigureAwait(false); }
static public void ClassInitialize(TestContext testContext) { var environment = TestUtil.InitializeEnvironment("E2E_FileUpload_CSharp_"); hubConnectionString = environment.Item1; registryManager = environment.Item2; hostName = TestUtil.GetHostName(hubConnectionString); serviceClient = ServiceClient.CreateFromConnectionString(hubConnectionString); fileNotificationReceiver = serviceClient.GetFileNotificationReceiver(); File.WriteAllBytes(smallFile, new byte[10 * 1024]); File.WriteAllBytes(bigFile, new byte[5120 * 1024]); }
private async Task UploadFile(Client.TransportType transport, string filename, bool x509auth = false) { TestDevice testDevice = await TestDevice.GetTestDeviceAsync( DevicePrefix, x509auth?TestDeviceType.X509 : TestDeviceType.Sasl).ConfigureAwait(false); DeviceClient deviceClient; if (x509auth) { X509Certificate2 cert = Configuration.IoTHub.GetCertificateWithPrivateKey(); var auth = new DeviceAuthenticationWithX509Certificate(testDevice.Id, cert); deviceClient = DeviceClient.Create(testDevice.IoTHubHostName, auth, transport); } else { deviceClient = DeviceClient.CreateFromConnectionString(testDevice.ConnectionString, transport); } using (deviceClient) using (ServiceClient serviceClient = ServiceClient.CreateFromConnectionString(Configuration.IoTHub.ConnectionString)) { FileNotificationReceiver <FileNotification> notificationReceiver = serviceClient.GetFileNotificationReceiver(); using (FileStream fileStreamSource = new FileStream(filename, FileMode.Open, FileAccess.Read)) { await deviceClient.UploadToBlobAsync(filename, fileStreamSource).ConfigureAwait(false); } FileNotification fileNotification = await VerifyFileNotification(notificationReceiver, testDevice.Id).ConfigureAwait(false); // The following checks allow running these tests multiple times in parallel. // Notifications for one of the test-run instances may be received by the other test-run. Assert.IsNotNull(fileNotification, "FileNotification is not received."); _log.WriteLine($"TestDevice: '{testDevice.Id}', blobName: '{fileNotification.BlobName}', size: {fileNotification.BlobSizeInBytes}"); Assert.IsFalse(string.IsNullOrEmpty(fileNotification.BlobUri), "File notification blob uri is null or empty"); await deviceClient.CloseAsync().ConfigureAwait(false); await serviceClient.CloseAsync().ConfigureAwait(false); } }
private async Task UploadFile(Client.TransportType transport, string filename, bool x509auth = false) { TestDevice testDevice = await TestDevice.GetTestDeviceAsync( DevicePrefix, x509auth ? TestDeviceType.X509 : TestDeviceType.Sasl).ConfigureAwait(false); DeviceClient deviceClient; if (x509auth) { X509Certificate2 cert = Configuration.IoTHub.GetCertificateWithPrivateKey(); var auth = new DeviceAuthenticationWithX509Certificate(testDevice.Id, cert); deviceClient = DeviceClient.Create(testDevice.IoTHubHostName, auth, transport); } else { deviceClient = DeviceClient.CreateFromConnectionString(testDevice.ConnectionString, transport); } using(deviceClient) using (ServiceClient serviceClient = ServiceClient.CreateFromConnectionString(Configuration.IoTHub.ConnectionString)) { FileNotificationReceiver<FileNotification> notificationReceiver = serviceClient.GetFileNotificationReceiver(); using (FileStream fileStreamSource = new FileStream(filename, FileMode.Open, FileAccess.Read)) { await deviceClient.UploadToBlobAsync(filename, fileStreamSource).ConfigureAwait(false); } FileNotification fileNotification = await VerifyFileNotification(notificationReceiver, testDevice.Id).ConfigureAwait(false); Assert.IsNotNull(fileNotification, "FileNotification is not received."); Assert.AreEqual(testDevice.Id + "/" + filename, fileNotification.BlobName, "Uploaded file name mismatch in notifications"); Assert.AreEqual(new FileInfo(filename).Length, fileNotification.BlobSizeInBytes, "Uploaded file size mismatch in notifications"); Assert.IsFalse(string.IsNullOrEmpty(fileNotification.BlobUri), "File notification blob uri is null or empty"); await deviceClient.CloseAsync().ConfigureAwait(false); await serviceClient.CloseAsync().ConfigureAwait(false); } }
async Task uploadFile(Client.TransportType transport, string filename) { Tuple <string, string> deviceInfo = TestUtil.CreateDevice("E2E_FileUpload_CSharp_", hostName, registryManager); var deviceClient = DeviceClient.CreateFromConnectionString(deviceInfo.Item2, transport); using (FileStream fileStreamSource = new FileStream(filename, FileMode.Open, FileAccess.Read)) { await deviceClient.UploadToBlobAsync(filename, fileStreamSource); } ServiceClient serviceClient = ServiceClient.CreateFromConnectionString(hubConnectionString); FileNotificationReceiver <FileNotification> fileNotificationReceiver = serviceClient.GetFileNotificationReceiver(); FileNotification fileNotification; while (true) { // Receive the file notification from queue fileNotification = await fileNotificationReceiver.ReceiveAsync(TimeSpan.FromSeconds(20)); Assert.IsNotNull(fileNotification); await fileNotificationReceiver.CompleteAsync(fileNotification); if (deviceInfo.Item1 == fileNotification.DeviceId) { break; } } Assert.AreEqual(deviceInfo.Item1 + "/" + filename, fileNotification.BlobName, "Uploaded file name mismatch in notifications"); Assert.AreEqual(new FileInfo(filename).Length, fileNotification.BlobSizeInBytes, "Uploaded file size mismatch in notifications"); Assert.IsFalse(string.IsNullOrEmpty(fileNotification.BlobUri), "File notification blob uri is null or empty"); await deviceClient.CloseAsync(); await serviceClient.CloseAsync(); TestUtil.RemoveDevice(deviceInfo.Item1, registryManager); }
private async Task ReceiveFileUploadNotifications(string targetDeviceId, CancellationToken cancellationToken) { if (!string.IsNullOrWhiteSpace(targetDeviceId)) { _logger.LogInformation($"Target device is specified, will only complete matching notifications."); } _logger.LogInformation($"Listening for file upload notifications from the service."); FileNotificationReceiver <FileNotification> notificationReceiver = _serviceClient.GetFileNotificationReceiver(); int totalNotificationsReceived = 0; int totalNotificationsCompleted = 0; int totalNotificationsAbandoned = 0; while (!cancellationToken.IsCancellationRequested) { try { FileNotification fileUploadNotification = await notificationReceiver.ReceiveAsync(s_notificationReceiverTimeout); if (fileUploadNotification == null) { _logger.LogInformation($"Did not receive any notification after {s_notificationReceiverTimeout.TotalSeconds} seconds."); continue; } totalNotificationsReceived++; _logger.LogInformation($"Received file upload notification."); _logger.LogInformation($"\tDeviceId: {fileUploadNotification.DeviceId ?? "N/A"}."); _logger.LogInformation($"\tFileName: {fileUploadNotification.BlobName ?? "N/A"}."); _logger.LogInformation($"\tEnqueueTimeUTC: {fileUploadNotification.EnqueuedTimeUtc}."); _logger.LogInformation($"\tBlobSizeInBytes: {fileUploadNotification.BlobSizeInBytes}."); // If the targetDeviceId is set and does not match the notification's origin, ignore it by abandoning the notification. // Completing a notification will remove that notification from the service's queue so it won't be delivered to any other receiver again. // Abandoning a notification will put it back on the queue to be re-delivered to receivers. This is mostly used when multiple receivers // are configured and each receiver is only interested in notifications from a particular device/s. if (!string.IsNullOrWhiteSpace(targetDeviceId) && !string.Equals(fileUploadNotification.DeviceId, targetDeviceId, StringComparison.OrdinalIgnoreCase)) { _logger.LogInformation($"Marking notification for {fileUploadNotification.DeviceId} as Abandoned."); await notificationReceiver.AbandonAsync(fileUploadNotification); _logger.LogInformation($"Successfully marked the notification for device {fileUploadNotification.DeviceId} as Abandoned."); totalNotificationsAbandoned++; } else { _logger.LogInformation($"Marking notification for {fileUploadNotification.DeviceId} as Completed."); await notificationReceiver.CompleteAsync(fileUploadNotification); _logger.LogInformation($"Successfully marked the notification for device {fileUploadNotification.DeviceId} as Completed."); totalNotificationsCompleted++; } } catch (Exception e) when((e is IotHubException) || (e is DeviceMessageLockLostException)) { _logger.LogWarning($"Caught a recoverable exception, will retry: {e.Message} - {e}"); } } _logger.LogInformation($"Total Notifications Received: {totalNotificationsReceived}."); _logger.LogInformation($"Total Notifications Marked as Completed: {totalNotificationsCompleted}."); _logger.LogInformation($"Total Notifications Marked as Abandoned: {totalNotificationsAbandoned}."); }
async Task uploadFileDisconnectTransport(Client.TransportType transport, string filename, string faultType, string reason, int delayInSec, int durationInSec = 0, int retryDurationInMilliSec = 24000) { Tuple <string, string> deviceInfo = TestUtil.CreateDevice(DevicePrefix, hostName, registryManager); DeviceClient deviceClient = DeviceClient.CreateFromConnectionString(deviceInfo.Item2, transport); deviceClient.OperationTimeoutInMilliseconds = (uint)retryDurationInMilliSec; Task fileuploadTask; using (FileStream fileStreamSource = new FileStream(filename, FileMode.Open, FileAccess.Read)) { fileuploadTask = deviceClient.UploadToBlobAsync(filename, fileStreamSource); // send error command after 400ms to allow time for the actual fileupload operation to start await Task.Delay(400); try { await deviceClient.SendEventAsync(TestUtil.ComposeErrorInjectionProperties(faultType, reason, delayInSec, durationInSec)); } catch (Exception) { // catch and ignore exceptions resulted from error injection and continue to // check result of the file upload status } await fileuploadTask; } ServiceClient serviceClient = ServiceClient.CreateFromConnectionString(hubConnectionString); FileNotificationReceiver <FileNotification> fileNotificationReceiver = serviceClient.GetFileNotificationReceiver(); FileNotification fileNotification; while (true) { // Receive the file notification from queue fileNotification = await fileNotificationReceiver.ReceiveAsync(TimeSpan.FromSeconds(20)); Assert.IsNotNull(fileNotification); await fileNotificationReceiver.CompleteAsync(fileNotification); if (deviceInfo.Item1 == fileNotification.DeviceId) { break; } } Assert.AreEqual(deviceInfo.Item1 + "/" + filename, fileNotification.BlobName, "Uploaded file name mismatch in notifications"); Assert.AreEqual(new FileInfo(filename).Length, fileNotification.BlobSizeInBytes, "Uploaded file size mismatch in notifications"); Assert.IsFalse(string.IsNullOrEmpty(fileNotification.BlobUri), "File notification blob uri is null or empty"); await deviceClient.CloseAsync(); await serviceClient.CloseAsync(); TestUtil.RemoveDevice(deviceInfo.Item1, registryManager); }