/// <summary>
        /// This method is called whenever the module is sent a message from the EdgeHub.
        /// It just pipe the messages without any change.
        /// It prints all the incoming messages.
        /// </summary>
        static async Task <MessageResponse> PipeMessage(Message message, object userContext)
        {
            var moduleClient = userContext as ModuleClient;

            if (moduleClient == null)
            {
                throw new InvalidOperationException("UserContext doesn't contain " + "expected values");
            }

            // Handle messages from leaf devices
            if (message.Properties.Keys.Contains(LeafDeviceIdPropertyName))
            {
                DeviceInfo leafDevice;
                string     leafDeviceId = message.Properties[LeafDeviceIdPropertyName];

                // Register the leaf device if not already registered
                if (!_leafDevices.Contains(leafDeviceId))
                {
                    // Not registered yet, so start new registration
                    leafDevice = _leafDevices.GetOrAdd(leafDeviceId);
                    if (leafDevice.Status == DeviceInfoStatus.New)
                    {
                        await RegisterLeafDevice(moduleClient, leafDevice, message.Properties[LeafDeviceModuleIdPropertyName]);
                    }
                }

                // Add message from leaf device to cache if not yet registered, otherwise pipe to IoTHub
                leafDevice = _leafDevices.Get(leafDeviceId);
                var leafDeviceMessage = CloneMessage(message);
                if (_cacheMessagesDuringRegistration && leafDevice.TryAddToWaitingList(leafDeviceMessage))
                {
                    Console.WriteLine($"Adding message from leaf device '{leafDeviceId}' on waiting list while waiting for registration completion.");
                }
                else if (leafDevice.Status == DeviceInfoStatus.Registered)
                {
                    try {
                        Console.WriteLine($"Sending message from leaf device '{leafDeviceId}' to IoTHub.");
                        await leafDevice.DeviceClient.SendEventAsync(leafDeviceMessage);
                    }
                    catch (Microsoft.Azure.Devices.Client.Exceptions.UnauthorizedException ex) {
                        Console.WriteLine($"ERROR: Leaf defice '{leafDeviceId}' unauthorized while sending event to IoTHub: {ex.Message}.");
                    }
                    finally {
                        leafDeviceMessage.Dispose();
                    }
                }
            }
            else
            {
                // Not a leaf device message so just pipe message to output
                using (var pipeMessage = CloneMessage(message))
                {
                    Console.WriteLine($"Pipe message from (non-leaf) device.");
                    await moduleClient.SendEventAsync("itmoutput", pipeMessage);
                }
            }

            return(MessageResponse.Completed);
        }