public async Task RunPart1StepsAsync(IChannel channel, ReadListeningHandler readHandler)
            {
                await this.ConnectAsync(channel, readHandler);

                await this.SubscribeAsync(channel, readHandler);

                await this.GetPart1SpecificSteps(channel, readHandler);
            }
            async Task GetPart1SpecificSteps(IChannel channel, ReadListeningHandler readHandler)
            {
                int publishQoS1PacketId = GetRandomPacketId();
                await channel.WriteAndFlushManyAsync(
                    new PublishPacket(QualityOfService.AtMostOnce, false, false)
                    {
                        //TopicName = string.Format("devices/{0}/messages/log/verbose/", clientId),
                        TopicName = $"devices/{this.clientId}/messages/events",
                        Payload = Unpooled.WrappedBuffer(Encoding.UTF8.GetBytes("{\"test\": \"telemetry-QoS0\"}"))
                    },
                    new PublishPacket(QualityOfService.AtLeastOnce, false, false)
                    {
                        PacketId = publishQoS1PacketId,
                        TopicName = $"devices/{this.clientId}/messages/events",
                        Payload = Unpooled.WrappedBuffer(Encoding.UTF8.GetBytes("{\"test\": \"telemetry\"}"))
                    });

                var packets = new Packet[5];
                for (int i = packets.Length - 1; i >= 0; i--)
                {
                    packets[i] = Assert.IsAssignableFrom<Packet>(await readHandler.ReceiveAsync());
                }

                PubAckPacket pubAckPacket = Assert.Single(packets.OfType<PubAckPacket>());
                Assert.Equal(publishQoS1PacketId, pubAckPacket.PacketId);

                PublishPacket publishQoS0Packet = Assert.Single(packets.OfType<PublishPacket>().Where(x => x.QualityOfService == QualityOfService.AtMostOnce));
                this.AssertPacketCoreValue(publishQoS0Packet, NotificationQoS0Content);

                PublishPacket publishQoS1Packet = Assert.Single(packets.OfType<PublishPacket>().Where(x => x.QualityOfService == QualityOfService.AtLeastOnce));
                this.AssertPacketCoreValue(publishQoS1Packet, NotificationQoS1Content);

                PublishPacket[] publishQoS2Packets = packets.OfType<PublishPacket>().Where(x => x.QualityOfService == QualityOfService.ExactlyOnce).Reverse().ToArray();
                Assert.Equal(2, publishQoS2Packets.Length);
                PublishPacket publishQoS2Packet1 = publishQoS2Packets[0];
                this.AssertPacketCoreValue(publishQoS2Packet1, NotificationQoS2Content);
                PublishPacket publishQoS2Packet2 = publishQoS2Packets[1];
                this.AssertPacketCoreValue(publishQoS2Packet2, NotificationQoS2Content2);

                await channel.WriteAndFlushManyAsync(
                    PubAckPacket.InResponseTo(publishQoS1Packet),
                    PubRecPacket.InResponseTo(publishQoS2Packet1),
                    PubRecPacket.InResponseTo(publishQoS2Packet2));

                var pubRelQoS2Packet1 = Assert.IsAssignableFrom<PubRelPacket>(await readHandler.ReceiveAsync());
                Assert.Equal(publishQoS2Packet1.PacketId, pubRelQoS2Packet1.PacketId);

                var pubRelQoS2Packet2 = Assert.IsAssignableFrom<PubRelPacket>(await readHandler.ReceiveAsync());
                Assert.Equal(publishQoS2Packet2.PacketId, pubRelQoS2Packet2.PacketId);

                await channel.WriteAndFlushManyAsync(
                    PubCompPacket.InResponseTo(pubRelQoS2Packet1),
                    DisconnectPacket.Instance);

                // device queue still contains QoS 2 packet 2 which was PUBRECed but not PUBCOMPed.
            }
        async Task ReceiveAndCompleteCommandAsync(IChannel clientChannel, ReadListeningHandler readHandler, IotHubConnectionStringBuilder hubConnectionStringBuilder, Device device)
        {
            var packet = Assert.IsType <PublishPacket>(await readHandler.ReceiveAsync());

            Assert.Equal($"devices/{this.deviceId}/messages/devicebound", packet.TopicName);
            Assert.Equal(MethodContent, Encoding.UTF8.GetString(packet.Payload.ToArray()));

            await clientChannel.WriteAndFlushManyAsync(PubAckPacket.InResponseTo(packet), PubRecPacket.InResponseTo(packet));

            var pubRelQoS2Packet2 = Assert.IsAssignableFrom <PubRelPacket>(await readHandler.ReceiveAsync());

            await clientChannel.WriteAndFlushManyAsync(
                PubCompPacket.InResponseTo(pubRelQoS2Packet2),
                DisconnectPacket.Instance);

            await this.EnsureDeviceQueueLengthAsync(hubConnectionStringBuilder.HostName, device, 0);
        }
            async Task SubscribeAsync(IChannel channel, ReadListeningHandler readHandler)
            {
                int subscribePacket1Id = GetRandomPacketId();
                int subscribePacket2Id = GetRandomPacketId();
                await channel.WriteAndFlushManyAsync(
                    new SubscribePacket(subscribePacket1Id, new SubscriptionRequest($"devices/{this.clientId}/messages/devicebound/#", QualityOfService.ExactlyOnce)),
                    new SubscribePacket(subscribePacket2Id, new SubscriptionRequest("multi/subscribe/check", QualityOfService.AtMostOnce)));

                var subAck1Packet = Assert.IsType<SubAckPacket>(await readHandler.ReceiveAsync());
                Assert.Equal(subscribePacket1Id, subAck1Packet.PacketId);
                Assert.Equal(1, subAck1Packet.ReturnCodes.Count);
                Assert.Equal(QualityOfService.ExactlyOnce, subAck1Packet.ReturnCodes[0]);

                var subAck2Packet = Assert.IsType<SubAckPacket>(await readHandler.ReceiveAsync());
                Assert.Equal(subscribePacket2Id, subAck2Packet.PacketId);
                Assert.Equal(1, subAck2Packet.ReturnCodes.Count);
                Assert.Equal(QualityOfService.AtMostOnce, subAck2Packet.ReturnCodes[0]);
            }
            async Task ConnectAsync(IChannel channel, ReadListeningHandler readHandler)
            {
                await channel.WriteAndFlushAsync(new ConnectPacket
                {
                    ClientId = this.clientId,
                    HasUsername = true,
                    Username = this.iotHubName + "/" + this.clientId,
                    HasPassword = true,
                    Password = this.password,
                    KeepAliveInSeconds = 120,
                    HasWill = true,
                    WillTopicName = "last/word",
                    WillMessage = Unpooled.WrappedBuffer(Encoding.UTF8.GetBytes("oops"))
                });

                var connAckPacket = Assert.IsType<ConnAckPacket>(await readHandler.ReceiveAsync());
                Assert.Equal(ConnectReturnCode.Accepted, connAckPacket.ReturnCode);
            }
            async Task GetPart2SpecificSteps(IChannel channel, ReadListeningHandler readHandler)
            {
                var packets = new Packet[2];
                for (int i = packets.Length - 1; i >= 0; i--)
                {
                    packets[i] = Assert.IsAssignableFrom<Packet>(await readHandler.ReceiveAsync());
                }

                PublishPacket qos1Packet = Assert.Single(packets.OfType<PublishPacket>());

                Assert.Equal(QualityOfService.AtLeastOnce, qos1Packet.QualityOfService);
                this.AssertPacketCoreValue(qos1Packet, Encoding.ASCII.GetString(qos1Packet.Payload.ToArray()));

                PubRelPacket pubRelQos2Packet = Assert.Single(packets.OfType<PubRelPacket>());

                await channel.WriteAndFlushManyAsync(
                    PubAckPacket.InResponseTo(qos1Packet),
                    PubCompPacket.InResponseTo(pubRelQos2Packet),
                    DisconnectPacket.Instance);
            }
        public async Task DeviceMethodTestAsync()
        {
            await this.EnsureServerInitializedAsync();

            int protocolGatewayPort = this.ProtocolGatewayPort;

            string iotHubConnectionString = ConfigurationManager.AppSettings["IotHubClient.ConnectionString"];
            IotHubConnectionStringBuilder hubConnectionStringBuilder = IotHubConnectionStringBuilder.Create(iotHubConnectionString);

            var device = await this.SetupDeviceAsync(iotHubConnectionString);

            await this.CleanupDeviceQueueAsync(hubConnectionStringBuilder.HostName, device);

            var clientScenarios = new ClientScenarios(hubConnectionStringBuilder.HostName, this.deviceId, this.deviceSas);

            var    group      = new MultithreadEventLoopGroup();
            string targetHost = this.tlsCertificate.GetNameInfo(X509NameType.DnsName, false);

            var       readHandler1 = new ReadListeningHandler(CommunicationTimeout);
            Bootstrap bootstrap    = new Bootstrap()
                                     .Group(group)
                                     .Channel <TcpSocketChannel>()
                                     .Option(ChannelOption.TcpNodelay, true)
                                     .Handler(this.ComposeClientChannelInitializer(targetHost, readHandler1));
            IChannel clientChannel = await bootstrap.ConnectAsync(this.ServerAddress, protocolGatewayPort);

            this.ScheduleCleanup(() => clientChannel.CloseAsync());

            // Connect + Subscribe
            await clientScenarios.ConnectAsync(clientChannel, readHandler1).WithTimeout(TestTimeout);

            await clientScenarios.SubscribeAsync(clientChannel, readHandler1).WithTimeout(TestTimeout);

            // Invoke method
            await this.InvokeMethodAsync(iotHubConnectionString, device);

            // Receive and complete
            await this.ReceiveAndCompleteCommandAsync(clientChannel, readHandler1, hubConnectionStringBuilder, device);
        }
 ActionChannelInitializer<ISocketChannel> ComposeClientChannelInitializer(string targetHost, ReadListeningHandler readHandler)
 {
     Func<Stream, SslStream> sslStreamFactoryFunc = stream => new SslStream(stream, true, (sender, certificate, chain, errors) => true);
     return new ActionChannelInitializer<ISocketChannel>(ch => ch.Pipeline.AddLast(
         new TlsHandler(sslStreamFactoryFunc,  new ClientTlsSettings(targetHost)),
         MqttEncoder.Instance,
         new MqttDecoder(false, 256 * 1024),
         new LoggingHandler("CLIENT"),
         readHandler,
         new XUnitLoggingHandler(this.output)));
 }
        public async Task BasicFunctionalityTest()
        {
            await this.EnsureServerInitializedAsync();

            int protocolGatewayPort = this.ProtocolGatewayPort;

            string iotHubConnectionString = ConfigurationManager.AppSettings["IotHubClient.ConnectionString"];
            IotHubConnectionStringBuilder hubConnectionStringBuilder = IotHubConnectionStringBuilder.Create(iotHubConnectionString);
            bool deviceNameProvided;
            this.deviceId = ConfigurationManager.AppSettings["End2End.DeviceName"];
            if (!string.IsNullOrEmpty(this.deviceId))
            {
                deviceNameProvided = true;
            }
            else
            {
                deviceNameProvided = false;
                this.deviceId = Guid.NewGuid().ToString("N");
            }

            RegistryManager registryManager = RegistryManager.CreateFromConnectionString(iotHubConnectionString);
            if (!deviceNameProvided)
            {
                await registryManager.AddDeviceAsync(new Device(this.deviceId));
                this.ScheduleCleanup(async () =>
                {
                    await registryManager.RemoveDeviceAsync(this.deviceId);
                    await registryManager.CloseAsync();
                });
            }

            Device device = await registryManager.GetDeviceAsync(this.deviceId);
            this.deviceSas =
                new SharedAccessSignatureBuilder
                {
                    Key = device.Authentication.SymmetricKey.PrimaryKey,
                    Target = $"{hubConnectionStringBuilder.HostName}/devices/{this.deviceId}",
                    KeyName = null,
                    TimeToLive = TimeSpan.FromMinutes(20)
                }
                    .ToSignature();

            EventHubClient eventHubClient = EventHubClient.CreateFromConnectionString(iotHubConnectionString, "messages/events");
            EventHubConsumerGroup ehGroup = eventHubClient.GetDefaultConsumerGroup();

            string[] partitionIds = (await eventHubClient.GetRuntimeInformationAsync()).PartitionIds;
            EventHubReceiver[] receivers = await Task.WhenAll(partitionIds.Select(pid => ehGroup.CreateReceiverAsync(pid.Trim(), DateTime.UtcNow)));

            ServiceClient serviceClient = ServiceClient.CreateFromConnectionString(iotHubConnectionString);

            Stopwatch sw = Stopwatch.StartNew();

            await this.CleanupDeviceQueueAsync(hubConnectionStringBuilder.HostName, device);

            var clientScenarios = new ClientScenarios(hubConnectionStringBuilder.HostName, this.deviceId, this.deviceSas);

            var group = new MultithreadEventLoopGroup();
            string targetHost = this.tlsCertificate.GetNameInfo(X509NameType.DnsName, false);

            var readHandler1 = new ReadListeningHandler(CommunicationTimeout);
            Bootstrap bootstrap = new Bootstrap()
                .Group(group)
                .Channel<TcpSocketChannel>()
                .Option(ChannelOption.TcpNodelay, true)
                .Handler(this.ComposeClientChannelInitializer(targetHost, readHandler1));
            IChannel clientChannel = await bootstrap.ConnectAsync(this.ServerAddress, protocolGatewayPort);
            this.ScheduleCleanup(() => clientChannel.CloseAsync());

            Task testWorkTask = Task.Run(async () =>
            {
                Tuple<EventData, string>[] ehMessages = await CollectEventHubMessagesAsync(receivers, 2);
                Tuple<EventData, string> qos0Event = Assert.Single(ehMessages.Where(x => TelemetryQoS0Content.Equals(x.Item2, StringComparison.Ordinal)));
                Tuple<EventData, string> qos1Event = Assert.Single(ehMessages.Where(x => TelemetryQoS1Content.Equals(x.Item2, StringComparison.Ordinal)));

                string qosPropertyName = ConfigurationManager.AppSettings["QoSPropertyName"];

                var qos0Notification = new Message(Encoding.UTF8.GetBytes(NotificationQoS0Content));
                qos0Notification.Properties[qosPropertyName] = "0";
                qos0Notification.Properties["subTopic"] = "tips";
                await serviceClient.SendAsync(this.deviceId, qos0Notification);

                var qos1Notification = new Message(Encoding.UTF8.GetBytes(NotificationQoS1Content));
                qos1Notification.Properties["subTopic"] = "firmware-update";
                await serviceClient.SendAsync(this.deviceId, qos1Notification);

                var qos2Notification = new Message(Encoding.UTF8.GetBytes(NotificationQoS2Content));
                qos2Notification.Properties[qosPropertyName] = "2";
                qos2Notification.Properties["subTopic"] = "critical-alert";
                await serviceClient.SendAsync(this.deviceId, qos2Notification);

                var qos2Notification2 = new Message(Encoding.UTF8.GetBytes(NotificationQoS2Content2));
                qos2Notification2.Properties[qosPropertyName] = "2";
                await serviceClient.SendAsync(this.deviceId, qos2Notification2);
            });

            await clientScenarios.RunPart1StepsAsync(clientChannel, readHandler1).WithTimeout(TestTimeout);
            await testWorkTask.WithTimeout(TestTimeout);

            this.output.WriteLine($"part 1 completed in {sw.Elapsed}");
            await this.EnsureDeviceQueueLengthAsync(hubConnectionStringBuilder.HostName, device, 1);
            this.output.WriteLine($"part 1 clean completed in {sw.Elapsed}");

            string part2Payload = Guid.NewGuid().ToString("N");
            await serviceClient.SendAsync(this.deviceId, new Message(Encoding.ASCII.GetBytes(part2Payload)));

            var readHandler2 = new ReadListeningHandler(CommunicationTimeout);
            IChannel clientChannelPart2 = await bootstrap
                .Handler(this.ComposeClientChannelInitializer(targetHost, readHandler2))
                .ConnectAsync(this.ServerAddress, protocolGatewayPort);
            this.ScheduleCleanup(async () =>
            {
                await clientChannelPart2.CloseAsync();
                await group.ShutdownGracefullyAsync();
            });

            await clientScenarios.RunPart2StepsAsync(clientChannelPart2, readHandler2).WithTimeout(TestTimeout);

            this.output.WriteLine($"Core test completed in {sw.Elapsed}");

            await this.EnsureDeviceQueueLengthAsync(hubConnectionStringBuilder.HostName, device, 0);
        }
Example #10
0
            async Task GetPart1SpecificSteps(IChannel channel, ReadListeningHandler readHandler)
            {
                int publishQoS1PacketId = 1003;
                await channel.WriteAndFlushManyAsync(
                    new PublishPacket(QualityOfService.AtMostOnce, false, false)
                {
                    //TopicName = string.Format("devices/{0}/messages/log/verbose/", clientId),
                    TopicName = $"devices/{this.clientId}/messages/events",
                    Payload   = Unpooled.WrappedBuffer(Encoding.UTF8.GetBytes("{\"test\": \"telemetry-QoS0\"}"))
                },
                    new PublishPacket(QualityOfService.AtLeastOnce, false, false)
                {
                    PacketId  = publishQoS1PacketId,
                    TopicName = $"devices/{this.clientId}/messages/events",
                    Payload   = Unpooled.WrappedBuffer(Encoding.UTF8.GetBytes("{\"test\": \"telemetry\"}"))
                });

                Packet[] packets = (await Task.WhenAll(Enumerable.Repeat(0, 6).Select(_ => readHandler.ReceiveAsync())))
                                   .Select(Assert.IsAssignableFrom <Packet>)
                                   .ToArray();

                PubAckPacket pubAckPacket = Assert.Single(packets.OfType <PubAckPacket>());

                Assert.Equal(publishQoS1PacketId, pubAckPacket.PacketId);

                PublishPacket publishQoS0Packet = Assert.Single(packets.OfType <PublishPacket>().Where(x => x.QualityOfService == QualityOfService.AtMostOnce));

                this.AssertPacketCoreValue(publishQoS0Packet, "tips", NotificationQoS0Content);

                PublishPacket[] publishQoS1Packets = packets.OfType <PublishPacket>().Where(x => x.QualityOfService == QualityOfService.AtLeastOnce).ToArray();
                Assert.Equal(2, publishQoS1Packets.Length);
                var qos1Notification = Assert.Single(publishQoS1Packets, x => x.TopicName.EndsWith("firmware-update"));

                this.AssertPacketCoreValue(qos1Notification, "firmware-update", NotificationQoS1Content);
                var methodCall = Assert.Single(publishQoS1Packets, x => x.TopicName.EndsWith("commands"));

                this.AssertPacketCoreValue(methodCall, "commands", MethodCallContent);

                PublishPacket[] publishQoS2Packets = packets.OfType <PublishPacket>().Where(x => x.QualityOfService == QualityOfService.ExactlyOnce).ToArray();
                Assert.Equal(2, publishQoS2Packets.Length);
                PublishPacket publishQoS2Packet1 = publishQoS2Packets[0];

                this.AssertPacketCoreValue(publishQoS2Packet1, "critical-alert", NotificationQoS2Content);
                PublishPacket publishQoS2Packet2 = publishQoS2Packets[1];

                this.AssertPacketCoreValue(publishQoS2Packet2, string.Empty, NotificationQoS2Content2);

                await channel.WriteAndFlushManyAsync(
                    PubAckPacket.InResponseTo(qos1Notification),
                    PubAckPacket.InResponseTo(methodCall),
                    PubRecPacket.InResponseTo(publishQoS2Packet1),
                    PubRecPacket.InResponseTo(publishQoS2Packet2));

                var pubRelQoS2Packet1 = Assert.IsAssignableFrom <PubRelPacket>(await readHandler.ReceiveAsync());

                Assert.Equal(publishQoS2Packet1.PacketId, pubRelQoS2Packet1.PacketId);

                var pubRelQoS2Packet2 = Assert.IsAssignableFrom <PubRelPacket>(await readHandler.ReceiveAsync());

                Assert.Equal(publishQoS2Packet2.PacketId, pubRelQoS2Packet2.PacketId);

                await channel.WriteAndFlushManyAsync(
                    PubCompPacket.InResponseTo(pubRelQoS2Packet1),
                    DisconnectPacket.Instance);

                // device queue still contains QoS 2 packet 2 which was PUBRECed but not PUBCOMPed.
            }