Esempio n. 1
0
        private static byte EncodePubCompPacket(MqttPubCompPacket packet, IMqttPacketWriter packetWriter)
        {
            ThrowIfPacketIdentifierIsInvalid(packet);

            if (!packet.ReasonCode.HasValue)
            {
                ThrowReasonCodeNotSetException();
            }

            packetWriter.Write(packet.PacketIdentifier.Value);

            var propertiesWriter = new MqttV500PropertiesWriter();

            if (packet.Properties != null)
            {
                propertiesWriter.WriteReasonString(packet.Properties.ReasonString);
                propertiesWriter.WriteUserProperties(packet.Properties.UserProperties);
            }

            if (propertiesWriter.Length > 0 || packet.ReasonCode.Value != MqttPubCompReasonCode.Success)
            {
                packetWriter.Write((byte)packet.ReasonCode.Value);
                propertiesWriter.WriteTo(packetWriter);
            }

            return(MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.PubComp));
        }
Esempio n. 2
0
        private Task HandleIncomingPubRelPacketAsync(IMqttChannelAdapter adapter, MqttPubRelPacket pubRelPacket, CancellationToken cancellationToken)
        {
            var response = new MqttPubCompPacket {
                PacketIdentifier = pubRelPacket.PacketIdentifier
            };

            return(adapter.SendPacketsAsync(_options.DefaultCommunicationTimeout, cancellationToken, response));
        }
        public void DeserializeV311_MqttPubCompPacket()
        {
            var p = new MqttPubCompPacket
            {
                PacketIdentifier = 123
            };

            DeserializeAndCompare(p, "cAIAew==");
        }
Esempio n. 4
0
        private Task ProcessReceivedPubRelPacket(MqttPubRelPacket pubRelPacket)
        {
            var response = new MqttPubCompPacket
            {
                PacketIdentifier = pubRelPacket.PacketIdentifier
            };

            return(SendAsync(response));
        }
Esempio n. 5
0
        private Task ProcessReceivedPubRelPacket(MqttPubRelPacket pubRelPacket, CancellationToken cancellationToken)
        {
            var response = new MqttPubCompPacket
            {
                PacketIdentifier = pubRelPacket.PacketIdentifier
            };

            return(SendAsync(response, cancellationToken));
        }
        private Task SerializeAsync(MqttPubCompPacket packet, IMqttCommunicationChannel destination)
        {
            using (var output = new MqttPacketWriter())
            {
                output.Write(packet.PacketIdentifier);

                output.InjectFixedHeader(MqttControlPacketType.PubComp);
                return(output.WriteToAsync(destination));
            }
        }
Esempio n. 7
0
        Task HandleIncomingPubRelPacketAsync(MqttPubRelPacket pubRelPacket, CancellationToken cancellationToken)
        {
            var pubCompPacket = new MqttPubCompPacket
            {
                PacketIdentifier = pubRelPacket.PacketIdentifier,
                ReasonCode       = MqttPubCompReasonCode.Success
            };

            return(SendAsync(pubCompPacket, cancellationToken));
        }
Esempio n. 8
0
        Task HandleIncomingPubCompPacket(MqttPubCompPacket pubCompPacket)
        {
            var acknowledgedPublishPacket = Session.AcknowledgePublishPacket(pubCompPacket.PacketIdentifier);

            if (acknowledgedPublishPacket != null)
            {
                return(ClientAcknowledgedPublishPacket(acknowledgedPublishPacket, pubCompPacket));
            }

            return(PlatformAbstractionLayer.CompletedTask);
        }
Esempio n. 9
0
        static byte EncodePubCompPacket(MqttPubCompPacket packet, IMqttPacketWriter packetWriter)
        {
            if (!packet.PacketIdentifier.HasValue)
            {
                throw new MqttProtocolViolationException("PubComp packet has no packet identifier.");
            }

            packetWriter.Write(packet.PacketIdentifier.Value);

            return(MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.PubComp));
        }
Esempio n. 10
0
        static byte EncodePubCompPacket(MqttPubCompPacket packet, MqttBufferWriter bufferWriter)
        {
            if (packet.PacketIdentifier == 0)
            {
                throw new MqttProtocolViolationException("PubComp packet has no packet identifier.");
            }

            bufferWriter.WriteTwoByteInteger(packet.PacketIdentifier);

            return(MqttBufferWriter.BuildFixedHeader(MqttControlPacketType.PubComp));
        }
Esempio n. 11
0
        private static MqttBasePacket DecodePubCompPacket(IMqttPacketBodyReader body)
        {
            ThrowIfBodyIsEmpty(body);

            var packet = new MqttPubCompPacket
            {
                PacketIdentifier = body.ReadTwoByteInteger()
            };

            if (body.EndOfStream)
            {
                packet.ReasonCode = MqttPubCompReasonCode.Success;
                return(packet);
            }

            packet.ReasonCode = (MqttPubCompReasonCode)body.ReadByte();

            var propertiesReader = new MqttV500PropertiesReader(body);

            while (propertiesReader.MoveNext())
            {
                if (packet.Properties == null)
                {
                    packet.Properties = new MqttPubCompPacketProperties();
                }

                if (propertiesReader.CurrentPropertyId == MqttPropertyId.ReasonString)
                {
                    packet.Properties.ReasonString = propertiesReader.ReadReasonString();
                }
                else if (propertiesReader.CurrentPropertyId == MqttPropertyId.UserProperty)
                {
                    if (packet.Properties.UserProperties == null)
                    {
                        packet.Properties.UserProperties = new List <MqttUserProperty>();
                    }

                    propertiesReader.AddUserPropertyTo(packet.Properties.UserProperties);
                }
                else
                {
                    propertiesReader.ThrowInvalidPropertyIdException(typeof(MqttPubCompPacket));
                }
            }

            return(packet);
        }
Esempio n. 12
0
        byte EncodePubCompPacket(MqttPubCompPacket packet)
        {
            ThrowIfPacketIdentifierIsInvalid(packet.PacketIdentifier, packet);

            _bufferWriter.WriteTwoByteInteger(packet.PacketIdentifier);

            _propertiesWriter.WriteReasonString(packet.ReasonString);
            _propertiesWriter.WriteUserProperties(packet.UserProperties);

            if (_propertiesWriter.Length > 0 || packet.ReasonCode != MqttPubCompReasonCode.Success)
            {
                _bufferWriter.WriteByte((byte)packet.ReasonCode);
                _propertiesWriter.WriteTo(_bufferWriter);
                _propertiesWriter.Reset();
            }

            return(MqttBufferWriter.BuildFixedHeader(MqttControlPacketType.PubComp));
        }
Esempio n. 13
0
        public MqttClientPublishResult Create(MqttPubRecPacket pubRecPacket, MqttPubCompPacket pubCompPacket)
        {
            if (pubRecPacket == null || pubCompPacket == null)
            {
                return(new MqttClientPublishResult
                {
                    ReasonCode = MqttClientPublishReasonCode.UnspecifiedError
                });
            }

            MqttClientPublishResult result;

            // The PUBCOMP is the last packet in QoS 2. So we use the results from that instead of PUBREC.
            if (pubCompPacket.ReasonCode == MqttPubCompReasonCode.PacketIdentifierNotFound)
            {
                result = new MqttClientPublishResult
                {
                    PacketIdentifier = pubCompPacket.PacketIdentifier,
                    ReasonCode       = MqttClientPublishReasonCode.UnspecifiedError,
                    ReasonString     = pubCompPacket.ReasonString,
                    UserProperties   = pubCompPacket.UserProperties ?? EmptyUserProperties
                };

                return(result);
            }

            result = new MqttClientPublishResult
            {
                PacketIdentifier = pubCompPacket.PacketIdentifier,
                ReasonCode       = MqttClientPublishReasonCode.Success,
                ReasonString     = pubCompPacket.ReasonString,
                UserProperties   = pubCompPacket.UserProperties ?? EmptyUserProperties
            };

            if (pubRecPacket.ReasonCode != MqttPubRecReasonCode.Success)
            {
                // Both enums share the same values.
                result.ReasonCode = (MqttClientPublishReasonCode)pubRecPacket.ReasonCode;
            }

            return(result);
        }
Esempio n. 14
0
        public void Serialize_Full_MqttPubCompPacket_V500()
        {
            var pubCompPacket = new MqttPubCompPacket
            {
                PacketIdentifier = 123,
                ReasonCode       = MqttPubCompReasonCode.PacketIdentifierNotFound,
                ReasonString     = "ReasonString",
                UserProperties   = new List <MqttUserProperty>
                {
                    new MqttUserProperty("Foo", "Bar")
                }
            };

            var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(pubCompPacket, MqttProtocolVersion.V500);

            Assert.AreEqual(pubCompPacket.PacketIdentifier, deserialized.PacketIdentifier);
            Assert.AreEqual(pubCompPacket.ReasonCode, deserialized.ReasonCode);
            Assert.AreEqual(pubCompPacket.ReasonString, deserialized.ReasonString);
            CollectionAssert.AreEqual(pubCompPacket.UserProperties, deserialized.UserProperties);
        }
        public void Serialize_Full_MqttPubCompPacket_V311()
        {
            var pubCompPacket = new MqttPubCompPacket
            {
                PacketIdentifier = 123,
                ReasonCode       = MqttPubCompReasonCode.PacketIdentifierNotFound,
                ReasonString     = "ReasonString",
                UserProperties   = new List <MqttUserProperty>
                {
                    new MqttUserProperty("Foo", "Bar")
                }
            };

            var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(pubCompPacket, MqttProtocolVersion.V311);

            Assert.AreEqual(pubCompPacket.PacketIdentifier, deserialized.PacketIdentifier);
            // ReasonCode not available in MQTTv3.
            // ReasonString not available in MQTTv3.
            // UserProperties not available in MQTTv3.
            Assert.IsNull(deserialized.UserProperties);
        }
        MqttPacket DecodePubCompPacket(ArraySegment <byte> body)
        {
            ThrowIfBodyIsEmpty(body);

            _bufferReader.SetBuffer(body.Array, body.Offset, body.Count);

            var packet = new MqttPubCompPacket
            {
                PacketIdentifier = _bufferReader.ReadTwoByteInteger()
            };

            if (_bufferReader.EndOfStream)
            {
                packet.ReasonCode = MqttPubCompReasonCode.Success;
                return(packet);
            }

            packet.ReasonCode = (MqttPubCompReasonCode)_bufferReader.ReadByte();

            var propertiesReader = new MqttV5PropertiesReader(_bufferReader);

            while (propertiesReader.MoveNext())
            {
                if (propertiesReader.CurrentPropertyId == MqttPropertyId.ReasonString)
                {
                    packet.ReasonString = propertiesReader.ReadReasonString();
                }
                else
                {
                    propertiesReader.ThrowInvalidPropertyIdException(typeof(MqttPubCompPacket));
                }
            }

            packet.UserProperties = propertiesReader.CollectedUserProperties;

            return(packet);
        }
        private void ProcessReceivedPacket(IMqttChannelAdapter adapter, MqttBasePacket packet, CancellationToken cancellationToken)
        {
            if (packet is MqttPublishPacket publishPacket)
            {
                HandleIncomingPublishPacket(adapter, publishPacket, cancellationToken);
                return;
            }

            if (packet is MqttPingReqPacket)
            {
                adapter.SendPacketAsync(new MqttPingRespPacket(), cancellationToken).GetAwaiter().GetResult();
                return;
            }

            if (packet is MqttPubRelPacket pubRelPacket)
            {
                var responsePacket = new MqttPubCompPacket
                {
                    PacketIdentifier = pubRelPacket.PacketIdentifier
                };

                adapter.SendPacketAsync(responsePacket, cancellationToken).GetAwaiter().GetResult();
                return;
            }

            if (packet is MqttPubRecPacket pubRecPacket)
            {
                var responsePacket = new MqttPubRelPacket
                {
                    PacketIdentifier = pubRecPacket.PacketIdentifier
                };

                adapter.SendPacketAsync(responsePacket, cancellationToken).GetAwaiter().GetResult();
                return;
            }

            if (packet is MqttPubAckPacket || packet is MqttPubCompPacket)
            {
                return;
            }

            if (packet is MqttSubscribePacket subscribePacket)
            {
                HandleIncomingSubscribePacket(adapter, subscribePacket, cancellationToken);
                return;
            }

            if (packet is MqttUnsubscribePacket unsubscribePacket)
            {
                HandleIncomingUnsubscribePacket(adapter, unsubscribePacket, cancellationToken);
                return;
            }

            if (packet is MqttDisconnectPacket)
            {
                Stop(MqttClientDisconnectType.Clean, true);
                return;
            }

            if (packet is MqttConnectPacket)
            {
                Stop(MqttClientDisconnectType.NotClean, true);
                return;
            }

            _logger.Warning(null, "Client '{0}': Received not supported packet ({1}). Closing connection.", ClientId, packet);
            Stop(MqttClientDisconnectType.NotClean, true);
        }
Esempio n. 18
0
        async Task RunInternalAsync()
        {
            var disconnectType = MqttClientDisconnectType.NotClean;

            try
            {
                _logger.Info("Client '{0}': Session started.", ClientId);

                _channelAdapter.ReadingPacketStartedCallback   = OnAdapterReadingPacketStarted;
                _channelAdapter.ReadingPacketCompletedCallback = OnAdapterReadingPacketCompleted;

                Session.WillMessage = ConnectPacket.WillMessage;

                Task.Run(() => SendPendingPacketsAsync(_cancellationToken.Token), _cancellationToken.Token).Forget(_logger);

                // TODO: Change to single thread in SessionManager. Or use SessionManager and stats from KeepAliveMonitor.
                _keepAliveMonitor.Start(ConnectPacket.KeepAlivePeriod, _cancellationToken.Token);

                await SendAsync(_channelAdapter.PacketFormatterAdapter.DataConverter.CreateConnAckPacket(_connectionValidatorContext)).ConfigureAwait(false);

                Session.IsCleanSession = false;

                while (!_cancellationToken.IsCancellationRequested)
                {
                    var packet = await _channelAdapter.ReceivePacketAsync(TimeSpan.Zero, _cancellationToken.Token).ConfigureAwait(false);

                    if (packet == null)
                    {
                        // The client has closed the connection gracefully.
                        break;
                    }

                    Interlocked.Increment(ref _sentPacketsCount);
                    _lastPacketReceivedTimestamp = DateTime.UtcNow;

                    if (!(packet is MqttPingReqPacket || packet is MqttPingRespPacket))
                    {
                        _lastNonKeepAlivePacketReceivedTimestamp = _lastPacketReceivedTimestamp;
                    }

                    _keepAliveMonitor.PacketReceived();

                    if (packet is MqttPublishPacket publishPacket)
                    {
                        await HandleIncomingPublishPacketAsync(publishPacket).ConfigureAwait(false);

                        continue;
                    }

                    if (packet is MqttPubRelPacket pubRelPacket)
                    {
                        var pubCompPacket = new MqttPubCompPacket
                        {
                            PacketIdentifier = pubRelPacket.PacketIdentifier,
                            ReasonCode       = MqttPubCompReasonCode.Success
                        };

                        await SendAsync(pubCompPacket).ConfigureAwait(false);

                        continue;
                    }

                    if (packet is MqttSubscribePacket subscribePacket)
                    {
                        await HandleIncomingSubscribePacketAsync(subscribePacket).ConfigureAwait(false);

                        continue;
                    }

                    if (packet is MqttUnsubscribePacket unsubscribePacket)
                    {
                        await HandleIncomingUnsubscribePacketAsync(unsubscribePacket).ConfigureAwait(false);

                        continue;
                    }

                    if (packet is MqttPingReqPacket)
                    {
                        await SendAsync(new MqttPingRespPacket()).ConfigureAwait(false);

                        continue;
                    }

                    if (packet is MqttDisconnectPacket)
                    {
                        Session.WillMessage = null;
                        disconnectType      = MqttClientDisconnectType.Clean;

                        StopInternal();
                        break;
                    }

                    _packetDispatcher.Dispatch(packet);
                }
            }
            catch (OperationCanceledException)
            {
            }
            catch (Exception exception)
            {
                if (exception is MqttCommunicationException)
                {
                    _logger.Warning(exception, "Client '{0}': Communication exception while receiving client packets.", ClientId);
                }
                else
                {
                    _logger.Error(exception, "Client '{0}': Error while receiving client packets.", ClientId);
                }

                StopInternal();
            }
            finally
            {
                if (_isTakeover)
                {
                    disconnectType = MqttClientDisconnectType.Takeover;
                }

                if (Session.WillMessage != null)
                {
                    _sessionsManager.DispatchApplicationMessage(Session.WillMessage, this);
                    Session.WillMessage = null;
                }

                _packetDispatcher.Reset();

                _channelAdapter.ReadingPacketStartedCallback   = null;
                _channelAdapter.ReadingPacketCompletedCallback = null;

                _packageReceiverTask = null;

                if (_isTakeover)
                {
                    try
                    {
                        // Don't use SendAsync here _cancellationToken is already cancelled.
                        await _channelAdapter.SendPacketAsync(new MqttDisconnectPacket
                        {
                            ReasonCode = MqttDisconnectReasonCode.SessionTakenOver
                        }, TimeSpan.Zero, CancellationToken.None).ConfigureAwait(false);
                    }
                    catch (Exception exception)
                    {
                        _logger.Error(exception, "Client '{0}': Error while sending DISCONNECT packet after takeover.", ClientId);
                    }
                }

                _logger.Info("Client '{0}': Connection stopped.", ClientId);

                try
                {
                    await _sessionsManager.CleanUpClient(ClientId, _channelAdapter, disconnectType);
                }
                catch (Exception e)
                {
                    _logger.Error(e, "Client '{0}': Error while cleaning up", ClientId);
                }
            }
        }
Esempio n. 19
0
        private async Task <MqttClientDisconnectType> RunInternalAsync()
        {
            var disconnectType = MqttClientDisconnectType.NotClean;

            try
            {
                _logger.Info("Client '{0}': Session started.", ClientId);

                _channelAdapter.ReadingPacketStartedCallback   = OnAdapterReadingPacketStarted;
                _channelAdapter.ReadingPacketCompletedCallback = OnAdapterReadingPacketCompleted;

                Session.WillMessage = _connectPacket.WillMessage;

#pragma warning disable 4014
                Task.Run(() => SendPendingPacketsAsync(_cancellationToken.Token), _cancellationToken.Token);
#pragma warning restore 4014

                // TODO: Change to single thread in SessionManager. Or use SessionManager and stats from KeepAliveMonitor.
                _keepAliveMonitor.Start(_connectPacket.KeepAlivePeriod, _cancellationToken.Token);

                await SendAsync(
                    new MqttConnAckPacket
                {
                    ReturnCode       = MqttConnectReturnCode.ConnectionAccepted,
                    ReasonCode       = MqttConnectReasonCode.Success,
                    IsSessionPresent = !Session.IsCleanSession
                }).ConfigureAwait(false);

                Session.IsCleanSession = false;

                while (!_cancellationToken.IsCancellationRequested)
                {
                    var packet = await _channelAdapter.ReceivePacketAsync(TimeSpan.Zero, _cancellationToken.Token).ConfigureAwait(false);

                    if (packet == null)
                    {
                        // The client has closed the connection gracefully.
                        break;
                    }

                    Interlocked.Increment(ref _sentPacketsCount);
                    _lastPacketReceivedTimestamp = DateTime.UtcNow;

                    if (!(packet is MqttPingReqPacket || packet is MqttPingRespPacket))
                    {
                        _lastNonKeepAlivePacketReceivedTimestamp = _lastPacketReceivedTimestamp;
                    }

                    _keepAliveMonitor.PacketReceived();

                    if (packet is MqttPublishPacket publishPacket)
                    {
                        await HandleIncomingPublishPacketAsync(publishPacket).ConfigureAwait(false);

                        continue;
                    }

                    if (packet is MqttPubRelPacket pubRelPacket)
                    {
                        var pubCompPacket = new MqttPubCompPacket
                        {
                            PacketIdentifier = pubRelPacket.PacketIdentifier,
                            ReasonCode       = MqttPubCompReasonCode.Success
                        };

                        await SendAsync(pubCompPacket).ConfigureAwait(false);

                        continue;
                    }

                    if (packet is MqttSubscribePacket subscribePacket)
                    {
                        await HandleIncomingSubscribePacketAsync(subscribePacket).ConfigureAwait(false);

                        continue;
                    }

                    if (packet is MqttUnsubscribePacket unsubscribePacket)
                    {
                        await HandleIncomingUnsubscribePacketAsync(unsubscribePacket).ConfigureAwait(false);

                        continue;
                    }

                    if (packet is MqttPingReqPacket)
                    {
                        await SendAsync(new MqttPingRespPacket()).ConfigureAwait(false);

                        continue;
                    }

                    if (packet is MqttDisconnectPacket)
                    {
                        Session.WillMessage = null;
                        disconnectType      = MqttClientDisconnectType.Clean;

                        StopInternal();
                        break;
                    }

                    _packetDispatcher.Dispatch(packet);
                }
            }
            catch (OperationCanceledException)
            {
            }
            catch (Exception exception)
            {
                if (exception is MqttCommunicationException)
                {
                    _logger.Warning(exception, "Client '{0}': Communication exception while receiving client packets.", ClientId);
                }
                else
                {
                    _logger.Error(exception, "Client '{0}': Unhandled exception while receiving client packets.", ClientId);
                }

                StopInternal();
            }
            finally
            {
                if (Session.WillMessage != null)
                {
                    _sessionsManager.DispatchApplicationMessage(Session.WillMessage, this);
                    Session.WillMessage = null;
                }

                _packetDispatcher.Reset();

                _channelAdapter.ReadingPacketStartedCallback   = null;
                _channelAdapter.ReadingPacketCompletedCallback = null;

                _logger.Info("Client '{0}': Session stopped.", ClientId);

                _packageReceiverTask = null;
            }

            return(disconnectType);
        }
Esempio n. 20
0
        public MqttClientPublishResult CreatePublishResult(MqttPubRecPacket pubRecPacket, MqttPubCompPacket pubCompPacket)
        {
            if (pubRecPacket == null || pubCompPacket == null)
            {
                return(new MqttClientPublishResult
                {
                    ReasonCode = MqttClientPublishReasonCode.UnspecifiedError
                });
            }

            return(new MqttClientPublishResult
            {
                PacketIdentifier = pubCompPacket.PacketIdentifier,
                ReasonCode = MqttClientPublishReasonCode.Success
            });
        }
Esempio n. 21
0
        private static byte Serialize(MqttPubCompPacket packet, MqttPacketWriter writer)
        {
            writer.Write(packet.PacketIdentifier);

            return(MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.PubComp));
        }