public async Task RunWebSocketConnectionAsync(WebSocket webSocket, HttpContext httpContext) { if (webSocket == null) { throw new ArgumentNullException(nameof(webSocket)); } var endpoint = $"{httpContext.Connection.RemoteIpAddress}:{httpContext.Connection.RemotePort}"; var clientCertificate = await httpContext.Connection.GetClientCertificateAsync().ConfigureAwait(false); var isSecureConnection = clientCertificate != null; clientCertificate?.Dispose(); var clientHandler = ClientHandler; if (clientHandler != null) { var writer = new SpanBasedMqttPacketWriter(); var formatter = new MqttPacketFormatterAdapter(writer); var channel = new MqttWebSocketChannel(webSocket, endpoint, isSecureConnection); using (var channelAdapter = new MqttChannelAdapter(channel, formatter, _logger.CreateChildLogger(nameof(MqttWebSocketServerAdapter)))) { await clientHandler(channelAdapter).ConfigureAwait(false); } } }
public void TestTryDeserialize() { var serializer = new MqttPacketFormatterAdapter(MqttProtocolVersion.V311, new MqttBufferWriter(4096, 65535)); var buffer = serializer.Encode(new MqttPublishPacket { Topic = "a", Payload = new byte[5] }).Join(); var sequence = new ReadOnlySequence <byte>(buffer.Array, buffer.Offset, buffer.Count); var part = sequence; MqttPacket packet; var consumed = part.Start; var observed = part.Start; var result = false; var read = 0; part = sequence.Slice(sequence.Start, 0); // empty message should fail result = serializer.TryDecode(part, out packet, out consumed, out observed, out read); Assert.IsFalse(result); part = sequence.Slice(sequence.Start, 1); // partial fixed header should fail result = serializer.TryDecode(part, out packet, out consumed, out observed, out read); Assert.IsFalse(result); part = sequence.Slice(sequence.Start, 4); // partial body should fail result = serializer.TryDecode(part, out packet, out consumed, out observed, out read); Assert.IsFalse(result); part = sequence; // complete msg should work result = serializer.TryDecode(part, out packet, out consumed, out observed, out read); Assert.IsTrue(result); }
public IMqttChannelAdapter CreateClientAdapter(IMqttClientOptions options) { if (options == null) { throw new ArgumentNullException(nameof(options)); } switch (options.ChannelOptions) { case MqttClientTcpOptions tcpOptions: { var endpoint = new DnsEndPoint(tcpOptions.Server, tcpOptions.GetPort()); var tcpConnection = new TcpConnection(endpoint); var writer = new SpanBasedMqttPacketWriter(); var formatter = new MqttPacketFormatterAdapter(options.ProtocolVersion, writer); return(new MqttConnectionContext(formatter, tcpConnection)); } default: { throw new NotSupportedException(); } } }
public IMqttChannelAdapter CreateClientAdapter(IMqttClientOptions options) { if (options == null) { throw new ArgumentNullException(nameof(options)); } IMqttChannel channel; switch (options.ChannelOptions) { case MqttClientTcpOptions _: { channel = new MqttTcpChannel(options); break; } case MqttClientWebSocketOptions webSocketOptions: { channel = new MqttWebSocketChannel(webSocketOptions); break; } default: { throw new NotSupportedException(); } } var packetFormatterAdapter = new MqttPacketFormatterAdapter(options.ProtocolVersion, new MqttPacketWriter()); return(new MqttChannelAdapter(channel, packetFormatterAdapter, options.PacketInspector, _logger)); }
MqttProtocolVersion DeserializeAndDetectVersion(MqttPacketFormatterAdapter packetFormatterAdapter, byte[] buffer) { var channel = new TestMqttChannel(buffer); var adapter = new MqttChannelAdapter(channel, packetFormatterAdapter, null, new MqttNetLogger()); adapter.ReceivePacketAsync(CancellationToken.None).GetAwaiter().GetResult(); return(packetFormatterAdapter.ProtocolVersion); //using (var headerStream = new MemoryStream(buffer)) //{ // //var fixedHeader = new byte[2]; // //var header = new MqttPacketReader(channel).ReadFixedHeaderAsync(fixedHeader, CancellationToken.None).GetAwaiter().GetResult().FixedHeader; // //using (var bodyStream = new MemoryStream(buffer, (int)headerStream.Position, (int)header.RemainingLength)) // //{ // // var reader = ReaderFactory(bodyStream.ToArray()); // // var packet = new ReceivedMqttPacket(header.Flags, reader, 0); // // packetFormatterAdapter.DetectProtocolVersion(packet); // // return adapter.ProtocolVersion; // //} //} }
void DeserializeAndCompare(MqttPacket packet, string expectedBase64Value, MqttProtocolVersion protocolVersion = MqttProtocolVersion.V311) { var writer = WriterFactory(); var serializer = MqttPacketFormatterAdapter.GetMqttPacketFormatter(protocolVersion, writer); var buffer1 = serializer.Encode(packet); using (var headerStream = new MemoryStream(buffer1.Join().ToArray())) { using (var channel = new TestMqttChannel(headerStream)) { using (var adapter = new MqttChannelAdapter( channel, new MqttPacketFormatterAdapter(protocolVersion, new MqttBufferWriter(4096, 65535)), null, new MqttNetEventLogger())) { var receivedPacket = adapter.ReceivePacketAsync(CancellationToken.None).GetAwaiter().GetResult(); var buffer2 = serializer.Encode(receivedPacket); Assert.AreEqual(expectedBase64Value, Convert.ToBase64String(buffer2.Join().ToArray())); } } } }
void DeserializeAndCompare(MqttBasePacket packet, string expectedBase64Value, MqttProtocolVersion protocolVersion = MqttProtocolVersion.V311) { var writer = WriterFactory(); var serializer = MqttPacketFormatterAdapter.GetMqttPacketFormatter(protocolVersion, writer); var buffer1 = serializer.Encode(packet); using (var headerStream = new MemoryStream(buffer1.ToArray())) { var channel = new TestMqttChannel(headerStream); var adapter = new MqttChannelAdapter(channel, new MqttPacketFormatterAdapter(protocolVersion, writer), null, new MqttNetLogger()); var receivedPacket = adapter.ReceivePacketAsync(CancellationToken.None).GetAwaiter().GetResult(); var buffer2 = serializer.Encode(receivedPacket); Assert.AreEqual(expectedBase64Value, Convert.ToBase64String(buffer2.ToArray())); //adapter.ReceivePacketAsync(CancellationToken.None); //var fixedHeader = new byte[2]; //var header = new MqttPacketReader(channel).ReadFixedHeaderAsync(fixedHeader, CancellationToken.None).GetAwaiter().GetResult().FixedHeader; //using (var bodyStream = new MemoryStream(Join(buffer1), (int)headerStream.Position, header.RemainingLength)) //{ // var reader = ReaderFactory(bodyStream.ToArray()); // var deserializedPacket = serializer.Decode(new ReceivedMqttPacket(header.Flags, reader, 0)); // var buffer2 = serializer.Encode(deserializedPacket); // Assert.AreEqual(expectedBase64Value, Convert.ToBase64String(Join(buffer2))); //} } }
TPacket Roundtrip <TPacket>(TPacket packet, MqttProtocolVersion protocolVersion = MqttProtocolVersion.V311) where TPacket : MqttBasePacket { var writer = WriterFactory(); var serializer = MqttPacketFormatterAdapter.GetMqttPacketFormatter(protocolVersion, writer); var buffer = serializer.Encode(packet); var channel = new TestMqttChannel(buffer.ToArray()); var adapter = new MqttChannelAdapter(channel, new MqttPacketFormatterAdapter(protocolVersion, writer), null, new MqttNetLogger()); return((TPacket)adapter.ReceivePacketAsync(CancellationToken.None).GetAwaiter().GetResult()); //using (var headerStream = new MemoryStream(buffer1.ToArray())) //{ // //var fixedHeader = new byte[2]; // //var header = new MqttPacketReader(channel).ReadFixedHeaderAsync(fixedHeader, CancellationToken.None).GetAwaiter().GetResult().FixedHeader; // //using (var bodyStream = new MemoryStream(Join(buffer1), (int)headerStream.Position, (int)header.RemainingLength)) // //{ // // var reader = ReaderFactory(bodyStream.ToArray()); // // return (T)serializer.Decode(new ReceivedMqttPacket(header.Flags, reader, 0)); // //} //} }
public void DetectVersionFromMqttConnectPacket() { var packet = new MqttConnectPacket { ClientId = "XYZ", Password = Encoding.UTF8.GetBytes("PASS"), Username = "******", KeepAlivePeriod = 123, CleanSession = true }; Assert.AreEqual( MqttProtocolVersion.V310, DeserializeAndDetectVersion(new MqttPacketFormatterAdapter(new MqttPacketWriter()), Serialize(packet, MqttProtocolVersion.V310))); Assert.AreEqual( MqttProtocolVersion.V311, DeserializeAndDetectVersion(new MqttPacketFormatterAdapter(new MqttPacketWriter()), Serialize(packet, MqttProtocolVersion.V311))); Assert.AreEqual( MqttProtocolVersion.V500, DeserializeAndDetectVersion(new MqttPacketFormatterAdapter(new MqttPacketWriter()), Serialize(packet, MqttProtocolVersion.V500))); var adapter = new MqttPacketFormatterAdapter(new MqttPacketWriter()); var ex = Assert.ThrowsException <MqttProtocolViolationException>(() => DeserializeAndDetectVersion(adapter, WriterFactory().AddMqttHeader(MqttControlPacketType.Connect, new byte[0]))); Assert.AreEqual("CONNECT packet must have at least 7 bytes.", ex.Message); ex = Assert.ThrowsException <MqttProtocolViolationException>(() => DeserializeAndDetectVersion(adapter, WriterFactory().AddMqttHeader(MqttControlPacketType.Connect, new byte[7]))); Assert.AreEqual("Protocol '' not supported.", ex.Message); ex = Assert.ThrowsException <MqttProtocolViolationException>(() => DeserializeAndDetectVersion(adapter, WriterFactory().AddMqttHeader(MqttControlPacketType.Connect, new byte[] { 255, 255, 0, 0, 0, 0, 0 }))); Assert.AreEqual("Expected at least 65537 bytes but there are only 7 bytes", ex.Message); }
public void Setup() { _packet = new MqttPublishPacket { Topic = "A" }; var serializer = new MqttPacketFormatterAdapter(MqttProtocolVersion.V311); var serializedPacket = Join(serializer.Encode(_packet)); _iterations = 10000; _stream = new MemoryStream(_iterations * serializedPacket.Length); for (var i = 0; i < _iterations; i++) { _stream.Write(serializedPacket, 0, serializedPacket.Length); } _stream.Position = 0; var channel = new TestMqttChannel(_stream); _channelAdapter = new MqttChannelAdapter(channel, serializer, new MqttNetLogger()); }
public async Task RunWebSocketConnectionAsync(WebSocket webSocket, HttpContext httpContext) { if (webSocket == null) { throw new ArgumentNullException(nameof(webSocket)); } var endpoint = $"{httpContext.Connection.RemoteIpAddress}:{httpContext.Connection.RemotePort}"; var clientCertificate = await httpContext.Connection.GetClientCertificateAsync().ConfigureAwait(false); try { var isSecureConnection = clientCertificate != null; var clientHandler = ClientHandler; if (clientHandler != null) { var formatter = new MqttPacketFormatterAdapter(new MqttBufferWriter(4096, 65535)); var channel = new MqttWebSocketChannel(webSocket, endpoint, isSecureConnection, clientCertificate); using (var channelAdapter = new MqttChannelAdapter(channel, formatter, null, _logger)) { await clientHandler(channelAdapter).ConfigureAwait(false); } } } finally { clientCertificate?.Dispose(); } }
MqttProtocolVersion DeserializeAndDetectVersion(MqttPacketFormatterAdapter packetFormatterAdapter, byte[] buffer) { var channel = new TestMqttChannel(buffer); var adapter = new MqttChannelAdapter(channel, packetFormatterAdapter, null, new MqttNetEventLogger()); adapter.ReceivePacketAsync(CancellationToken.None).GetAwaiter().GetResult(); return(packetFormatterAdapter.ProtocolVersion); }
public async Task TestLargePacket() { var serializer = new MqttPacketFormatterAdapter(MqttProtocolVersion.V311); var pipe = new DuplexPipeMockup(); var connection = new DefaultConnectionContext(); connection.Transport = pipe; var ctx = new MqttConnectionContext(serializer, connection); await ctx.SendPacketAsync(new MqttPublishPacket { Payload = new byte[20_000] }, CancellationToken.None).ConfigureAwait(false);
public MqttPacket Decode(MqttPacketBuffer buffer) { using (var channel = new MemoryMqttChannel(buffer.ToArray())) { var formatterAdapter = new MqttPacketFormatterAdapter(_protocolVersion, new MqttBufferWriter(4096, 65535)); var adapter = new MqttChannelAdapter(channel, formatterAdapter, null, MqttNetNullLogger.Instance); return adapter.ReceivePacketAsync(CancellationToken.None).GetAwaiter().GetResult(); } }
public MqttPacketSerializationHelper(MqttProtocolVersion protocolVersion = MqttProtocolVersion.V311, MqttBufferWriter bufferWriter = null) { _protocolVersion = protocolVersion; if (bufferWriter == null) { bufferWriter = new MqttBufferWriter(4096, 65535); } _packetFormatter = MqttPacketFormatterAdapter.GetMqttPacketFormatter(_protocolVersion, bufferWriter); }
public MqttConnectionContext(MqttPacketFormatterAdapter packetFormatterAdapter, ConnectionContext connection) { PacketFormatterAdapter = packetFormatterAdapter ?? throw new ArgumentNullException(nameof(packetFormatterAdapter)); Connection = connection ?? throw new ArgumentNullException(nameof(connection)); if (Connection.Transport != null) { _input = Connection.Transport.Input; _output = Connection.Transport.Output; } }
async void OnConnectionReceivedAsync(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args) { try { var clientHandler = ClientHandler; if (clientHandler != null) { X509Certificate2 clientCertificate = null; if (args.Socket.Control.ClientCertificate != null) { try { clientCertificate = new X509Certificate2(args.Socket.Control.ClientCertificate.GetCertificateBlob().ToArray()); } catch (Exception exception) { _logger.Warning(exception, "Unable to convert UWP certificate to X509Certificate2."); } } var bufferWriter = new MqttBufferWriter(4096, 65535); var packetFormatterAdapter = new MqttPacketFormatterAdapter(bufferWriter); var tcpChannel = new MqttTcpChannel(args.Socket, clientCertificate, _options); using (var clientAdapter = new MqttChannelAdapter(tcpChannel, packetFormatterAdapter, null, _rootLogger)) { await clientHandler(clientAdapter).ConfigureAwait(false); } } } catch (Exception exception) { if (exception is ObjectDisposedException) { // It can happen that the listener socket is accessed after the cancellation token is already set and the listener socket is disposed. return; } _logger.Error(exception, "Error while handling client connection."); } finally { try { args.Socket.Dispose(); } catch (Exception exception) { _logger.Error(exception, "Error while cleaning up client connection."); } } }
TPacket Roundtrip <TPacket>(TPacket packet, MqttProtocolVersion protocolVersion = MqttProtocolVersion.V311, MqttBufferWriter bufferWriter = null) where TPacket : MqttPacket { var writer = bufferWriter ?? WriterFactory(); var serializer = MqttPacketFormatterAdapter.GetMqttPacketFormatter(protocolVersion, writer); var buffer = serializer.Encode(packet); using (var channel = new TestMqttChannel(buffer.Join().ToArray())) { var adapter = new MqttChannelAdapter(channel, new MqttPacketFormatterAdapter(protocolVersion, new MqttBufferWriter(4096, 65535)), null, new MqttNetEventLogger()); return((TPacket)adapter.ReceivePacketAsync(CancellationToken.None).GetAwaiter().GetResult()); } }
public async Task TestReceivePacketAsyncThrowsWhenReaderCompleted() { var serializer = new MqttPacketFormatterAdapter(MqttProtocolVersion.V311); var pipe = new DuplexPipeMockup(); var connection = new DefaultConnectionContext(); connection.Transport = pipe; var ctx = new MqttConnectionContext(serializer, connection); pipe.Receive.Writer.Complete(); await Assert.ThrowsExceptionAsync <MqttCommunicationException>(() => ctx.ReceivePacketAsync(CancellationToken.None)); }
public MqttChannelAdapter(IMqttChannel channel, MqttPacketFormatterAdapter packetFormatterAdapter, IMqttPacketInspector packetInspector, IMqttNetLogger logger) { _channel = channel ?? throw new ArgumentNullException(nameof(channel)); PacketFormatterAdapter = packetFormatterAdapter ?? throw new ArgumentNullException(nameof(packetFormatterAdapter)); _packetInspectorHandler = new MqttPacketInspectorHandler(packetInspector, logger); if (logger == null) { throw new ArgumentNullException(nameof(logger)); } _logger = logger.WithSource(nameof(MqttChannelAdapter)); }
public MqttChannelAdapter(IMqttChannel channel, MqttPacketFormatterAdapter packetFormatterAdapter, IMqttNetChildLogger logger) { if (logger == null) { throw new ArgumentNullException(nameof(logger)); } _channel = channel ?? throw new ArgumentNullException(nameof(channel)); PacketFormatterAdapter = packetFormatterAdapter ?? throw new ArgumentNullException(nameof(packetFormatterAdapter)); _packetReader = new MqttPacketReader(_channel); _logger = logger.CreateChildLogger(nameof(MqttChannelAdapter)); }
public async Task OnConnectedAsync(ConnectionContext connection) { try { var formatter = new MqttPacketFormatterAdapter(new MqttBufferWriter(4096, 65535)); var context = new MqttConnectionContext(formatter, connection); Context.TrySetResult(context); await ClientHandler(context); } catch (Exception ex) { Context.TrySetException(ex); } }
public async Task OnConnectedAsync(ConnectionContext connection) { try { var writer = new SpanBasedMqttPacketWriter(); var formatter = new MqttPacketFormatterAdapter(writer); var context = new MqttConnectionContext(formatter, connection); Context.TrySetResult(context); await ClientHandler(context); } catch (Exception ex) { Context.TrySetException(ex); } }
public async Task TestCorruptedConnectPacket() { var writer = new MqttPacketWriter(); var serializer = new MqttPacketFormatterAdapter(writer); var pipe = new DuplexPipeMockup(); var connection = new DefaultConnectionContext(); connection.Transport = pipe; var ctx = new MqttConnectionContext(serializer, connection); await pipe.Receive.Writer.WriteAsync(writer.AddMqttHeader(MqttControlPacketType.Connect, new byte[0])); await Assert.ThrowsExceptionAsync <MqttProtocolViolationException>(() => ctx.ReceivePacketAsync(CancellationToken.None)); // the first exception should complete the pipes so if someone tries to use the connection after that it should throw immidiatly await Assert.ThrowsExceptionAsync <InvalidOperationException>(() => ctx.ReceivePacketAsync(CancellationToken.None)); }
public async Task TestParallelWrites() { var serializer = new MqttPacketFormatterAdapter(MqttProtocolVersion.V311); var pipe = new DuplexPipeMockup(); var connection = new DefaultConnectionContext(); connection.Transport = pipe; var ctx = new MqttConnectionContext(serializer, connection); var tasks = Enumerable.Range(1, 10).Select(_ => Task.Run(async() => { for (int i = 0; i < 100; i++) { await ctx.SendPacketAsync(new MqttPublishPacket(), TimeSpan.Zero, CancellationToken.None).ConfigureAwait(false); } })); await Task.WhenAll(tasks).ConfigureAwait(false); }
public override async Task OnConnectedAsync(ConnectionContext connection) { // required for websocket transport to work var transferFormatFeature = connection.Features.Get <ITransferFormatFeature>(); if (transferFormatFeature != null) { transferFormatFeature.ActiveFormat = TransferFormat.Binary; } var formatter = new MqttPacketFormatterAdapter(new MqttBufferWriter(_serverOptions.WriterBufferSize, _serverOptions.WriterBufferSizeMax)); using (var adapter = new MqttConnectionContext(formatter, connection)) { var clientHandler = ClientHandler; if (clientHandler != null) { await clientHandler(adapter).ConfigureAwait(false); } } }
private T Roundtrip <T>(T packet, MqttProtocolVersion protocolVersion = MqttProtocolVersion.V311) where T : MqttBasePacket { var writer = WriterFactory(); var serializer = MqttPacketFormatterAdapter.GetMqttPacketFormatter(protocolVersion, writer); var buffer1 = serializer.Encode(packet); using (var headerStream = new MemoryStream(Join(buffer1))) { var channel = new TestMqttChannel(headerStream); var fixedHeader = new byte[2]; var header = new MqttPacketReader(channel).ReadFixedHeaderAsync(fixedHeader, CancellationToken.None).GetAwaiter().GetResult().FixedHeader; using (var bodyStream = new MemoryStream(Join(buffer1), (int)headerStream.Position, (int)header.RemainingLength)) { var reader = ReaderFactory(bodyStream.ToArray()); return((T)serializer.Decode(new ReceivedMqttPacket(header.Flags, reader, 0))); } } }
public IMqttChannelAdapter CreateClientAdapter(MqttClientOptions options, MqttPacketInspector packetInspector, IMqttNetLogger logger) { if (options == null) { throw new ArgumentNullException(nameof(options)); } switch (options.ChannelOptions) { case MqttClientTcpOptions tcpOptions: { var endpoint = new DnsEndPoint(tcpOptions.Server, tcpOptions.GetPort()); var tcpConnection = new TcpConnection(endpoint); var formatter = new MqttPacketFormatterAdapter(options.ProtocolVersion, new MqttBufferWriter(4096, 65535)); return(new MqttConnectionContext(formatter, tcpConnection)); } default: { throw new NotSupportedException(); } } }
byte[] Serialize(MqttPacket packet, MqttProtocolVersion protocolVersion) { return(MqttPacketFormatterAdapter.GetMqttPacketFormatter(protocolVersion, WriterFactory()).Encode(packet).Join().ToArray()); }
public static bool TryDecode(this MqttPacketFormatterAdapter formatter, SpanBasedMqttPacketBodyReader reader, in ReadOnlySequence <byte> input,