protected override async Task GetScenario(IChannel channel, ReadListeningHandler readHandler, string clientId, CancellationToken cancellationToken) { await GetSubscribeSteps(channel, readHandler, clientId); await GetPublishSteps(channel, readHandler, clientId, QualityOfService.AtLeastOnce, "devices/{0}/messages/events", 10, 138, 353); }
async Task GetCompleteScenarioAsync(IChannel channel, ReadListeningHandler readHandler, string clientId, string password, CancellationToken cancellationToken) { await channel.WriteAndFlushAsync(new ConnectPacket { ClientId = clientId, CleanSession = false, HasUsername = true, Username = clientId, HasPassword = true, Password = password, KeepAliveInSeconds = 120 }); object message = await readHandler.ReceiveAsync(); var connackPacket = message as ConnAckPacket; if (connackPacket == null) { throw new InvalidOperationException(string.Format("{1}: Expected CONNACK, received {0}", message, clientId)); } else if (connackPacket.ReturnCode != ConnectReturnCode.Accepted) { throw new InvalidOperationException(string.Format("{1}: Expected successful CONNACK, received CONNACK with return code of {0}", connackPacket.ReturnCode, clientId)); } await this.GetScenario(channel, readHandler, clientId, cancellationToken); }
public async Task <Task> StartAsync(string deviceId, CancellationToken cancellationToken) { string deviceSas = new SharedAccessSignatureBuilder { Key = this.deviceKey, Target = $"{this.connectionStringBuilder.HostName}/devices/{deviceId}", TimeToLive = TimeSpan.FromDays(3) } .ToSignature(); var taskCompletionSource = new TaskCompletionSource(); Bootstrap b = this.bootstrap.Clone(); var readHandler = new ReadListeningHandler(CommunicationTimeout); b.Handler(new ActionChannelInitializer <ISocketChannel>( ch => { ch.Pipeline.AddLast( new TlsHandler(stream => new SslStream(stream, true, (sender, certificate, chain, errors) => true), new ClientTlsSettings(this.tlsHostName)), MqttEncoder.Instance, new MqttDecoder(false, 256 * 1024), readHandler, ConsoleLoggingHandler.Instance); })); var channel = await b.ConnectAsync(this.endpoint); await this.GetCompleteScenarioAsync(channel, readHandler, deviceId, deviceSas, cancellationToken); return(taskCompletionSource.Task); }
public async Task MqttWebSocketClientAndServerScenario() { var websocket = new ClientWebSocket(); websocket.Options.AddSubProtocol(WebSocketConstants.SubProtocols.Mqtt); Uri uri = new Uri("ws://" + IotHubName + ":" + Port + WebSocketConstants.UriSuffix); await websocket.ConnectAsync(uri, CancellationToken.None); var clientReadListener = new ReadListeningHandler(); var clientChannel = new ClientWebSocketChannel(null, websocket); clientChannel .Option(ChannelOption.Allocator, UnpooledByteBufferAllocator.Default) .Option(ChannelOption.AutoRead, true) .Option(ChannelOption.RcvbufAllocator, new AdaptiveRecvByteBufAllocator()) .Option(ChannelOption.MessageSizeEstimator, DefaultMessageSizeEstimator.Default); clientChannel.Pipeline.AddLast( MqttEncoder.Instance, new MqttDecoder(false, 256 * 1024), clientReadListener); var clientWorkerGroup = new MultithreadEventLoopGroup(); await clientWorkerGroup.GetNext().RegisterAsync(clientChannel); await Task.WhenAll(RunMqttClientScenarioAsync(clientChannel, clientReadListener), RunMqttServerScenarioAsync(serverWebSocketChannel, serverListener)); done = true; }
public async Task<Task> StartAsync(string deviceId, CancellationToken cancellationToken) { string deviceSas = new SharedAccessSignatureBuilder { Key = this.deviceKey, Target = $"{this.connectionStringBuilder.HostName}/devices/{deviceId}", TimeToLive = TimeSpan.FromDays(3) } .ToSignature(); var taskCompletionSource = new TaskCompletionSource(); Bootstrap b = this.bootstrap.Clone(); var readHandler = new ReadListeningHandler(CommunicationTimeout); b.Handler(new ActionChannelInitializer<ISocketChannel>( ch => { ch.Pipeline.AddLast( new TlsHandler(stream => new SslStream(stream, true, (sender, certificate, chain, errors) => true), new ClientTlsSettings(this.tlsHostName)), MqttEncoder.Instance, new MqttDecoder(false, 256 * 1024), readHandler, ConsoleLoggingHandler.Instance); })); var channel = await b.ConnectAsync(this.endpoint); await this.GetCompleteScenarioAsync(channel, readHandler, deviceId, deviceSas, cancellationToken); return taskCompletionSource.Task; }
static async Task RunMqttServerScenarioAsync(IChannel channel, ReadListeningHandler readListener) { var connectPacket = await readListener.ReceiveAsync(DefaultTimeout) as ConnectPacket; Assert.IsNotNull(connectPacket, "Must be a Connect pkt"); // todo verify await channel.WriteAndFlushAsync(new ConnAckPacket { ReturnCode = ConnectReturnCode.Accepted, SessionPresent = true }); var subscribePacket = await readListener.ReceiveAsync(DefaultTimeout) as SubscribePacket; Assert.IsNotNull(subscribePacket); // todo verify await channel.WriteAndFlushAsync(SubAckPacket.InResponseTo(subscribePacket, QualityOfService.ExactlyOnce)); var unsubscribePacket = await readListener.ReceiveAsync(DefaultTimeout) as UnsubscribePacket; Assert.IsNotNull(unsubscribePacket); // todo verify await channel.WriteAndFlushAsync(UnsubAckPacket.InResponseTo(unsubscribePacket)); var publishQos0Packet = await readListener.ReceiveAsync(DefaultTimeout) as PublishPacket; Assert.IsNotNull(publishQos0Packet); // todo verify var publishQos1Packet = await readListener.ReceiveAsync(DefaultTimeout) as PublishPacket; Assert.IsNotNull(publishQos1Packet); // todo verify int publishQos1PacketId = GetRandomPacketId(); await channel.WriteAndFlushManyAsync( PubAckPacket.InResponseTo(publishQos1Packet), new PublishPacket(QualityOfService.AtLeastOnce, false, false) { PacketId = publishQos1PacketId, TopicName = PublishS2CQos1Topic, Payload = Unpooled.WrappedBuffer(Encoding.UTF8.GetBytes(PublishS2CQos1Payload)) }); var pubAckPacket = await readListener.ReceiveAsync(DefaultTimeout) as PubAckPacket; Assert.AreEqual(publishQos1PacketId, pubAckPacket.PacketId); var disconnectPacket = await readListener.ReceiveAsync(DefaultTimeout) as DisconnectPacket; Assert.IsNotNull(disconnectPacket); }
protected override async Task GetScenario(IChannel channel, ReadListeningHandler readHandler, string clientId, CancellationToken cancellationToken) { await GetSubscribeSteps(channel, readHandler, clientId); while (!cancellationToken.IsCancellationRequested) { await GetPublishSteps(channel, readHandler, clientId, QualityOfService.AtLeastOnce, "devices/{0}/messages/events", 1, 138, 353); await channel.EventLoop.ScheduleAsync(() => { }, TimeSpan.FromMinutes(1), cancellationToken); } }
protected static async Task GetSubscribeSteps(IChannel channel, ReadListeningHandler readHandler, string clientId, string topicNamePattern) { int subscribePacketId = Random.Next(1, ushort.MaxValue); await channel.WriteAndFlushAsync( new SubscribePacket( subscribePacketId, new SubscriptionRequest(string.Format(topicNamePattern, clientId), QualityOfService.ExactlyOnce))); object message = await readHandler.ReceiveAsync(); var subackPacket = message as SubAckPacket; if (subackPacket == null) { throw new InvalidOperationException(string.Format("{1}: Expected SUBACK, received {0}", message, clientId)); } else if (subackPacket.PacketId == subscribePacketId && subackPacket.ReturnCodes[0] > QualityOfService.ExactlyOnce) { throw new InvalidOperationException($"{clientId}: Expected successful SUBACK({subscribePacketId.ToString()}), received SUBACK({subackPacket.PacketId.ToString()}) with QoS={subackPacket.ReturnCodes[0].ToString()}"); } }
public async Task ClientWebSocketChannelReadAfterCloseTest() { var websocket = new ClientWebSocket(); websocket.Options.AddSubProtocol(WebSocketConstants.SubProtocols.Mqtt); var uri = new Uri("ws://" + IotHubName + ":" + Port + WebSocketConstants.UriSuffix); await websocket.ConnectAsync(uri, CancellationToken.None); var clientReadListener = new ReadListeningHandler(); var clientChannel = new ClientWebSocketChannel(null, websocket); clientChannel .Option(ChannelOption.Allocator, UnpooledByteBufferAllocator.Default) .Option(ChannelOption.AutoRead, true) .Option(ChannelOption.RcvbufAllocator, new AdaptiveRecvByteBufAllocator()) .Option(ChannelOption.MessageSizeEstimator, DefaultMessageSizeEstimator.Default); clientChannel.Pipeline.AddLast( clientReadListener); var threadLoop = new SingleThreadEventLoop("MQTTExecutionThread", TimeSpan.FromSeconds(1)); await threadLoop.RegisterAsync(clientChannel); await clientChannel.CloseAsync(); // Test Read API try { await clientReadListener.ReceiveAsync(DefaultTimeout); Assert.Fail("Should have thrown InvalidOperationException"); } catch (InvalidOperationException e) { Assert.IsTrue(e.Message.Contains("Channel is closed")); } done = true; }
static async Task RunWebSocketServer() { HttpListenerContext context = await listener.GetContextAsync(); if (!context.Request.IsWebSocketRequest) { context.Response.StatusCode = (int)HttpStatusCode.BadRequest; context.Response.Close(); } HttpListenerWebSocketContext webSocketContext = await context.AcceptWebSocketAsync(WebSocketConstants.SubProtocols.Mqtt, 8 * 1024, TimeSpan.FromMinutes(5)); serverListener = new ReadListeningHandler(); serverWebSocketChannel = new ServerWebSocketChannel(null, webSocketContext.WebSocket, context.Request.RemoteEndPoint); serverWebSocketChannel .Option(ChannelOption.Allocator, UnpooledByteBufferAllocator.Default) .Option(ChannelOption.AutoRead, true) .Option(ChannelOption.RcvbufAllocator, new AdaptiveRecvByteBufAllocator()) .Option(ChannelOption.MessageSizeEstimator, DefaultMessageSizeEstimator.Default); serverWebSocketChannel.Pipeline.AddLast("server logger", new LoggingHandler("SERVER")); serverWebSocketChannel.Pipeline.AddLast( MqttEncoder.Instance, new MqttDecoder(true, 256 * 1024), serverListener); var workerGroup = new MultithreadEventLoopGroup(); await workerGroup.GetNext().RegisterAsync(serverWebSocketChannel); while (true) { if (done) { break; } await Task.Delay(TimeSpan.FromSeconds(2)); } }
protected static async Task GetPublishSteps(IChannel channel, ReadListeningHandler readHandler, string clientId, QualityOfService qos, string topicNamePattern, int count, int minPayloadSize, int maxPayloadSize) { Contract.Requires(count > 0); Contract.Requires(qos < QualityOfService.ExactlyOnce); PublishPacket[] publishPackets = Enumerable.Repeat(0, count) .Select(_ => new PublishPacket(qos, false, false) { TopicName = string.Format(topicNamePattern, clientId), PacketId = Random.Next(1, ushort.MaxValue), Payload = GetPayloadBuffer(Random.Next(minPayloadSize, maxPayloadSize)) }) .ToArray(); await channel.WriteAndFlushManyAsync(publishPackets); if (qos == QualityOfService.AtMostOnce) { return; } int acked = 0; do { object receivedMessage = await readHandler.ReceiveAsync(); var pubackPacket = receivedMessage as PubAckPacket; if (pubackPacket == null || pubackPacket.PacketId != publishPackets[acked].PacketId) { throw new InvalidOperationException($"{clientId}: Expected PUBACK({publishPackets[acked].PacketId.ToString()}), received {receivedMessage}"); } acked++; }while (acked < count); }
protected static Task GetSubscribeSteps(IChannel channel, ReadListeningHandler readHandler, string clientId) { return GetSubscribeSteps(channel, readHandler, clientId, "devices/{0}/messages/devicebound"); }
static async Task RunMqttClientScenarioAsync(IChannel channel, ReadListeningHandler readListener) { await channel.WriteAndFlushAsync(new ConnectPacket { ClientId = ClientId, Username = "******", Password = "******", WillTopicName = "last/word", WillMessage = Unpooled.WrappedBuffer(Encoding.UTF8.GetBytes("oops")) }); var connAckPacket = await readListener.ReceiveAsync(DefaultTimeout) as ConnAckPacket; Assert.IsNotNull(connAckPacket); Assert.AreEqual(ConnectReturnCode.Accepted, connAckPacket.ReturnCode); int subscribePacketId = GetRandomPacketId(); int unsubscribePacketId = GetRandomPacketId(); await channel.WriteAndFlushManyAsync( new SubscribePacket(subscribePacketId, new SubscriptionRequest(SubscribeTopicFilter1, QualityOfService.ExactlyOnce), new SubscriptionRequest(SubscribeTopicFilter2, QualityOfService.AtLeastOnce), new SubscriptionRequest("for/unsubscribe", QualityOfService.AtMostOnce)), new UnsubscribePacket(unsubscribePacketId, "for/unsubscribe")); var subAckPacket = await readListener.ReceiveAsync(DefaultTimeout) as SubAckPacket; Assert.IsNotNull(subAckPacket); Assert.AreEqual(subscribePacketId, subAckPacket.PacketId); Assert.AreEqual(3, subAckPacket.ReturnCodes.Count); Assert.AreEqual(QualityOfService.ExactlyOnce, subAckPacket.ReturnCodes[0]); Assert.AreEqual(QualityOfService.AtLeastOnce, subAckPacket.ReturnCodes[1]); Assert.AreEqual(QualityOfService.AtMostOnce, subAckPacket.ReturnCodes[2]); var unsubAckPacket = await readListener.ReceiveAsync(DefaultTimeout) as UnsubAckPacket; Assert.IsNotNull(unsubAckPacket); Assert.AreEqual(unsubscribePacketId, unsubAckPacket.PacketId); int publishQoS1PacketId = GetRandomPacketId(); await channel.WriteAndFlushManyAsync( new PublishPacket(QualityOfService.AtMostOnce, false, false) { TopicName = PublishC2STopic, Payload = Unpooled.WrappedBuffer(Encoding.UTF8.GetBytes(PublishC2SQos0Payload)) }, new PublishPacket(QualityOfService.AtLeastOnce, false, false) { PacketId = publishQoS1PacketId, TopicName = PublishC2SQos1Topic, Payload = Unpooled.WrappedBuffer(Encoding.UTF8.GetBytes(PublishC2SQos1Payload)) }); //new PublishPacket(QualityOfService.AtLeastOnce, false, false) { TopicName = "feedback/qos/One", Payload = Unpooled.WrappedBuffer(Encoding.UTF8.GetBytes("QoS 1 test. Different data length.")) }); var pubAckPacket = await readListener.ReceiveAsync(DefaultTimeout) as PubAckPacket; Assert.IsNotNull(pubAckPacket); Assert.AreEqual(publishQoS1PacketId, pubAckPacket.PacketId); var publishPacket = await readListener.ReceiveAsync(DefaultTimeout) as PublishPacket; Assert.IsNotNull(publishPacket); Assert.AreEqual(QualityOfService.AtLeastOnce, publishPacket.QualityOfService); Assert.AreEqual(PublishS2CQos1Topic, publishPacket.TopicName); Assert.AreEqual(PublishS2CQos1Payload, publishPacket.Payload.ToString(Encoding.UTF8)); await channel.WriteAndFlushManyAsync( PubAckPacket.InResponseTo(publishPacket), DisconnectPacket.Instance); }
public async Task EchoServerAndClient() { var testPromise = new DefaultPromise(); var tlsCertificate = TestResourceHelper.GetTestCertificate(); Func <Task> closeServerFunc = await this.StartServerAsync(true, ch => { ch.Pipeline.AddLast("server logger", new LoggingHandler("SERVER")); ch.Pipeline.AddLast("server tls", TlsHandler.Server(tlsCertificate)); ch.Pipeline.AddLast("server logger2", new LoggingHandler("SER***")); ch.Pipeline.AddLast("server prepender", new LengthFieldPrepender2(2)); ch.Pipeline.AddLast("server decoder", new LengthFieldBasedFrameDecoder2(ushort.MaxValue, 0, 2, 0, 2)); ch.Pipeline.AddLast(new EchoChannelHandler()); }, testPromise); var group = new MultithreadEventLoopGroup(); var readListener = new ReadListeningHandler(DefaultTimeout); Bootstrap b = new Bootstrap() .Group(group) .Channel <TcpSocketChannel>() .Option(ChannelOption.TcpNodelay, true) .Handler(new ActionChannelInitializer <ISocketChannel>(ch => { string targetHost = tlsCertificate.GetNameInfo(X509NameType.DnsName, false); var clientTlsSettings = new ClientTlsSettings(targetHost); ch.Pipeline.AddLast("client logger", new LoggingHandler("CLIENT")); ch.Pipeline.AddLast("client tls", new TlsHandler(stream => new SslStream(stream, true, (sender, certificate, chain, errors) => true), clientTlsSettings)); ch.Pipeline.AddLast("client logger2", new LoggingHandler("CLI***")); ch.Pipeline.AddLast("client prepender", new LengthFieldPrepender2(2)); ch.Pipeline.AddLast("client decoder", new LengthFieldBasedFrameDecoder2(ushort.MaxValue, 0, 2, 0, 2)); ch.Pipeline.AddLast(readListener); })); this.Output.WriteLine("Configured Bootstrap: {0}", b); IChannel clientChannel = null; try { clientChannel = await b.ConnectAsync(IPAddress.Loopback, Port); this.Output.WriteLine("Connected channel: {0}", clientChannel); string[] messages = { "message 1", string.Join(",", Enumerable.Range(1, 300)) }; foreach (string message in messages) { await clientChannel.WriteAndFlushAsync(Unpooled.WrappedBuffer(Encoding.UTF8.GetBytes(message))).WithTimeout(DefaultTimeout); var responseMessage = Assert.IsAssignableFrom <IByteBuffer>(await readListener.ReceiveAsync()); Assert.Equal(message, responseMessage.ToString(Encoding.UTF8)); } testPromise.TryComplete(); await testPromise.Task.WithTimeout(TimeSpan.FromMinutes(5)); } finally { Task serverCloseTask = closeServerFunc(); clientChannel?.CloseAsync().Wait(TimeSpan.FromSeconds(5)); group.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(5)).Wait(TimeSpan.FromSeconds(10)); if (!serverCloseTask.Wait(ShutdownTimeout)) { this.Output.WriteLine("Didn't stop in time."); } } }
public async Task MqttServerAndClient() { var testPromise = new DefaultPromise(); var tlsCertificate = TestResourceHelper.GetTestCertificate(); var serverReadListener = new ReadListeningHandler(); IChannel serverChannel = null; Func <Task> closeServerFunc = await this.StartServerAsync(true, ch => { serverChannel = ch; ch.Pipeline.AddLast("server logger", new LoggingHandler("SERVER")); ch.Pipeline.AddLast("server tls", TlsHandler.Server(tlsCertificate)); ch.Pipeline.AddLast("server logger2", new LoggingHandler("SER***")); ch.Pipeline.AddLast( MqttEncoder.Instance, new MqttDecoder(true, 256 * 1024), serverReadListener); }, testPromise); var group = new MultithreadEventLoopGroup(); var clientReadListener = new ReadListeningHandler(); Bootstrap b = new Bootstrap() .Group(group) .Channel <TcpSocketChannel>() .Option(ChannelOption.TcpNodelay, true) .Handler(new ActionChannelInitializer <ISocketChannel>(ch => { string targetHost = tlsCertificate.GetNameInfo(X509NameType.DnsName, false); var clientTlsSettings = new ClientTlsSettings(targetHost); ch.Pipeline.AddLast("client logger", new LoggingHandler("CLIENT")); ch.Pipeline.AddLast("client tls", new TlsHandler(stream => new SslStream(stream, true, (sender, certificate, chain, errors) => true), clientTlsSettings)); ch.Pipeline.AddLast("client logger2", new LoggingHandler("CLI***")); ch.Pipeline.AddLast( MqttEncoder.Instance, new MqttDecoder(false, 256 * 1024), clientReadListener); })); this.Output.WriteLine("Configured Bootstrap: {0}", b); IChannel clientChannel = null; try { clientChannel = await b.ConnectAsync(IPAddress.Loopback, Port); this.Output.WriteLine("Connected channel: {0}", clientChannel); await Task.WhenAll(this.RunMqttClientScenarioAsync(clientChannel, clientReadListener), this.RunMqttServerScenarioAsync(serverChannel, serverReadListener)) .WithTimeout(TimeSpan.FromMinutes(5)); testPromise.TryComplete(); await testPromise.Task; } finally { Task serverCloseTask = closeServerFunc(); clientChannel?.CloseAsync().Wait(TimeSpan.FromSeconds(5)); group.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(5)).Wait(TimeSpan.FromSeconds(10)); if (!serverCloseTask.Wait(ShutdownTimeout)) { this.Output.WriteLine("Didn't stop in time."); } } }
protected static async Task GetPublishSteps(IChannel channel, ReadListeningHandler readHandler, string clientId, QualityOfService qos, string topicNamePattern, int count, int minPayloadSize, int maxPayloadSize) { Contract.Requires(count > 0); Contract.Requires(qos < QualityOfService.ExactlyOnce); PublishPacket[] publishPackets = Enumerable.Repeat(0, count) .Select(_ => new PublishPacket(qos, false, false) { TopicName = string.Format(topicNamePattern, clientId), PacketId = Random.Next(1, ushort.MaxValue), Payload = GetPayloadBuffer(Random.Next(minPayloadSize, maxPayloadSize)) }) .ToArray(); await channel.WriteAndFlushManyAsync(publishPackets); if (qos == QualityOfService.AtMostOnce) { return; } int acked = 0; do { object receivedMessage = await readHandler.ReceiveAsync(); var pubackPacket = receivedMessage as PubAckPacket; if (pubackPacket == null || pubackPacket.PacketId != publishPackets[acked].PacketId) { throw new InvalidOperationException($"{clientId}: Expected PUBACK({publishPackets[acked].PacketId.ToString()}), received {receivedMessage}"); } acked++; } while (acked < count); }
protected static Task GetSubscribeSteps(IChannel channel, ReadListeningHandler readHandler, string clientId) { return(GetSubscribeSteps(channel, readHandler, clientId, "devices/{0}/messages/devicebound")); }
protected virtual Task GetScenario(IChannel channel, ReadListeningHandler readHandler, string clientId, CancellationToken cancellationToken) { return TaskEx.Completed; }
protected virtual Task GetScenario(IChannel channel, ReadListeningHandler readHandler, string clientId, CancellationToken cancellationToken) { return(TaskEx.Completed); }