Example #1
0
        public ICollection <ArraySegment <byte> > Serialize(MqttBasePacket packet)
        {
            if (packet == null)
            {
                throw new ArgumentNullException(nameof(packet));
            }

            using (var stream = new MemoryStream(128))
                using (var writer = new MqttPacketWriter(stream))
                {
                    var fixedHeader     = SerializePacket(packet, writer);
                    var remainingLength = (int)stream.Length;
                    writer.Write(fixedHeader);
                    MqttPacketWriter.WriteRemainingLength(remainingLength, writer);
                    var headerLength = (int)stream.Length - remainingLength;

#if NET461 || NET452 || NETSTANDARD2_0
                    var buffer = stream.GetBuffer();
#else
                    var buffer = stream.ToArray();
#endif
                    return(new List <ArraySegment <byte> >
                    {
                        new ArraySegment <byte>(buffer, remainingLength, headerLength),
                        new ArraySegment <byte>(buffer, 0, remainingLength)
                    });
                }
        }
Example #2
0
        private byte SerializePacket(MqttBasePacket packet, MqttPacketWriter writer)
        {
            switch (packet)
            {
            case MqttConnectPacket connectPacket: return(Serialize(connectPacket, writer));

            case MqttConnAckPacket connAckPacket: return(Serialize(connAckPacket, writer));

            case MqttDisconnectPacket _: return(SerializeEmptyPacket(MqttControlPacketType.Disconnect));

            case MqttPingReqPacket _: return(SerializeEmptyPacket(MqttControlPacketType.PingReq));

            case MqttPingRespPacket _: return(SerializeEmptyPacket(MqttControlPacketType.PingResp));

            case MqttPublishPacket publishPacket: return(Serialize(publishPacket, writer));

            case MqttPubAckPacket pubAckPacket: return(Serialize(pubAckPacket, writer));

            case MqttPubRecPacket pubRecPacket: return(Serialize(pubRecPacket, writer));

            case MqttPubRelPacket pubRelPacket: return(Serialize(pubRelPacket, writer));

            case MqttPubCompPacket pubCompPacket: return(Serialize(pubCompPacket, writer));

            case MqttSubscribePacket subscribePacket: return(Serialize(subscribePacket, writer));

            case MqttSubAckPacket subAckPacket: return(Serialize(subAckPacket, writer));

            case MqttUnsubscribePacket unsubscribePacket: return(Serialize(unsubscribePacket, writer));

            case MqttUnsubAckPacket unsubAckPacket: return(Serialize(unsubAckPacket, writer));

            default: throw new MqttProtocolViolationException("Packet type invalid.");
            }
        }
Example #3
0
        private static byte Serialize(MqttSubscribePacket packet, MqttPacketWriter packetWriter)
        {
            if (!packet.TopicFilters.Any())
            {
                throw new MqttProtocolViolationException("At least one topic filter must be set [MQTT-3.8.3-3].");
            }

            if (!packet.PacketIdentifier.HasValue)
            {
                throw new MqttProtocolViolationException("Subscribe packet has no packet identifier.");
            }

            packetWriter.Write(packet.PacketIdentifier.Value);

            if (packet.TopicFilters?.Count > 0)
            {
                foreach (var topicFilter in packet.TopicFilters)
                {
                    packetWriter.WriteWithLengthPrefix(topicFilter.Topic);
                    packetWriter.Write((byte)topicFilter.QualityOfServiceLevel);
                }
            }

            return(MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.Subscribe, 0x02));
        }
Example #4
0
        public ArraySegment <byte> Serialize(MqttBasePacket packet)
        {
            if (packet == null)
            {
                throw new ArgumentNullException(nameof(packet));
            }

            // Leave enough head space for max header size (fixed + 4 variable remaining length = 5 bytes)
            _packetWriter.Reset();
            _packetWriter.Seek(5);

            var fixedHeader     = SerializePacket(packet, _packetWriter);
            var remainingLength = _packetWriter.Length - 5;

            var remainingLengthBuffer = MqttPacketWriter.EncodeRemainingLength(remainingLength);

            var headerSize   = FixedHeaderSize + remainingLengthBuffer.Count;
            var headerOffset = 5 - headerSize;

            // Position cursor on correct offset on beginining of array (has leading 0x0)
            _packetWriter.Seek(headerOffset);
            _packetWriter.Write(fixedHeader);
            _packetWriter.Write(remainingLengthBuffer.Array, remainingLengthBuffer.Offset, remainingLengthBuffer.Count);

            var buffer = _packetWriter.GetBuffer();

            return(new ArraySegment <byte>(buffer, headerOffset, _packetWriter.Length - headerOffset));
        }
Example #5
0
        private byte Serialize(MqttConnAckPacket packet, MqttPacketWriter packetWriter)
        {
            if (ProtocolVersion == MqttProtocolVersion.V310)
            {
                packetWriter.Write(0);
            }
            else if (ProtocolVersion == MqttProtocolVersion.V311)
            {
                byte connectAcknowledgeFlags = 0x0;
                if (packet.IsSessionPresent)
                {
                    connectAcknowledgeFlags |= 0x1;
                }

                packetWriter.Write(connectAcknowledgeFlags);
            }
            else
            {
                throw new MqttProtocolViolationException("Protocol version not supported.");
            }

            packetWriter.Write((byte)packet.ConnectReturnCode);

            return(MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.ConnAck));
        }
Example #6
0
        private byte Serialize(MqttConnectPacket packet, MqttPacketWriter writer)
        {
            ValidateConnectPacket(packet);

            // Write variable header
            writer.Write(0x00, 0x04); // 3.1.2.1 Protocol Name
            if (ProtocolVersion == MqttProtocolVersion.V311)
            {
                writer.Write(ProtocolVersionV311Name);
                writer.Write(0x04); // 3.1.2.2 Protocol Level (4)
            }
            else
            {
                writer.Write(ProtocolVersionV310Name);
                writer.Write(0x64, 0x70, 0x03); // Protocol Level (0x03)
            }

            var connectFlags = new ByteWriter(); // 3.1.2.3 Connect Flags

            connectFlags.Write(false);           // Reserved
            connectFlags.Write(packet.CleanSession);
            connectFlags.Write(packet.WillMessage != null);

            if (packet.WillMessage != null)
            {
                connectFlags.Write((int)packet.WillMessage.QualityOfServiceLevel, 2);
                connectFlags.Write(packet.WillMessage.Retain);
            }
            else
            {
                connectFlags.Write(0, 2);
                connectFlags.Write(false);
            }

            connectFlags.Write(packet.Password != null);
            connectFlags.Write(packet.Username != null);

            writer.Write(connectFlags);
            writer.Write(packet.KeepAlivePeriod);
            writer.WriteWithLengthPrefix(packet.ClientId);

            if (packet.WillMessage != null)
            {
                writer.WriteWithLengthPrefix(packet.WillMessage.Topic);
                writer.WriteWithLengthPrefix(packet.WillMessage.Payload);
            }

            if (packet.Username != null)
            {
                writer.WriteWithLengthPrefix(packet.Username);
            }

            if (packet.Password != null)
            {
                writer.WriteWithLengthPrefix(packet.Password);
            }

            return(MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.Connect));
        }
Example #7
0
        private static byte Serialize(MqttUnsubAckPacket packet, MqttPacketWriter packetWriter)
        {
            if (!packet.PacketIdentifier.HasValue)
            {
                throw new MqttProtocolViolationException("UnsubAck packet has no packet identifier.");
            }

            packetWriter.Write(packet.PacketIdentifier.Value);
            return(MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.UnsubAck));
        }
Example #8
0
        private static byte Serialize(MqttPubRelPacket packet, MqttPacketWriter writer)
        {
            if (!packet.PacketIdentifier.HasValue)
            {
                throw new MqttProtocolViolationException("PubRel packet has no packet identifier.");
            }

            writer.Write(packet.PacketIdentifier.Value);

            return(MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.PubRel, 0x02));
        }
Example #9
0
        private static byte Serialize(MqttSubAckPacket packet, MqttPacketWriter writer)
        {
            writer.Write(packet.PacketIdentifier);

            if (packet.SubscribeReturnCodes?.Any() == true)
            {
                foreach (var packetSubscribeReturnCode in packet.SubscribeReturnCodes)
                {
                    writer.Write((byte)packetSubscribeReturnCode);
                }
            }

            return(MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.SubAck));
        }
Example #10
0
        private byte Serialize(MqttConnAckPacket packet, MqttPacketWriter writer)
        {
            var connectAcknowledgeFlags = new ByteWriter();

            if (ProtocolVersion == MqttProtocolVersion.V311)
            {
                connectAcknowledgeFlags.Write(packet.IsSessionPresent);
            }

            writer.Write(connectAcknowledgeFlags);
            writer.Write((byte)packet.ConnectReturnCode);

            return(MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.ConnAck));
        }
Example #11
0
        private static byte Serialize(MqttPublishPacket packet, MqttPacketWriter packetWriter)
        {
            ValidatePublishPacket(packet);

            packetWriter.WriteWithLengthPrefix(packet.Topic);

            if (packet.QualityOfServiceLevel > MqttQualityOfServiceLevel.AtMostOnce)
            {
                if (!packet.PacketIdentifier.HasValue)
                {
                    throw new MqttProtocolViolationException("Publish packet has no packet identifier.");
                }

                packetWriter.Write(packet.PacketIdentifier.Value);
            }
            else
            {
                if (packet.PacketIdentifier > 0)
                {
                    throw new MqttProtocolViolationException("Packet identifier must be empty if QoS == 0 [MQTT-2.3.1-5].");
                }
            }

            if (packet.Payload?.Length > 0)
            {
                packetWriter.Write(packet.Payload, 0, packet.Payload.Length);
            }

            byte fixedHeader = 0;

            if (packet.Retain)
            {
                fixedHeader |= 0x01;
            }

            fixedHeader |= (byte)((byte)packet.QualityOfServiceLevel << 1);

            if (packet.Dup)
            {
                fixedHeader |= 0x08;
            }

            return(MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.Publish, fixedHeader));
        }
Example #12
0
        private static byte Serialize(MqttUnsubscribePacket packet, MqttPacketWriter writer)
        {
            if (!packet.TopicFilters.Any())
            {
                throw new MqttProtocolViolationException("At least one topic filter must be set [MQTT-3.10.3-2].");
            }

            writer.Write(packet.PacketIdentifier);

            if (packet.TopicFilters?.Any() == true)
            {
                foreach (var topicFilter in packet.TopicFilters)
                {
                    writer.WriteWithLengthPrefix(topicFilter);
                }
            }

            return(MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.Unsubscibe, 0x02));
        }
Example #13
0
        private static byte Serialize(MqttSubAckPacket packet, MqttPacketWriter packetWriter)
        {
            if (!packet.PacketIdentifier.HasValue)
            {
                throw new MqttProtocolViolationException("SubAck packet has no packet identifier.");
            }

            packetWriter.Write(packet.PacketIdentifier.Value);

            if (packet.SubscribeReturnCodes?.Any() == true)
            {
                foreach (var packetSubscribeReturnCode in packet.SubscribeReturnCodes)
                {
                    packetWriter.Write((byte)packetSubscribeReturnCode);
                }
            }

            return(MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.SubAck));
        }
Example #14
0
 private static byte SerializeEmptyPacket(MqttControlPacketType type)
 {
     return(MqttPacketWriter.BuildFixedHeader(type));
 }
Example #15
0
 private static byte Serialize(IMqttPacketWithIdentifier packet, BinaryWriter writer)
 {
     writer.Write(packet.PacketIdentifier);
     return(MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.UnsubAck));
 }
Example #16
0
        private static byte Serialize(MqttPubCompPacket packet, MqttPacketWriter writer)
        {
            writer.Write(packet.PacketIdentifier);

            return(MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.PubComp));
        }
Example #17
0
        private byte Serialize(MqttConnectPacket packet, MqttPacketWriter packetWriter)
        {
            ValidateConnectPacket(packet);

            // Write variable header
            if (ProtocolVersion == MqttProtocolVersion.V311)
            {
                packetWriter.WriteWithLengthPrefix("MQTT");
                packetWriter.Write(4); // 3.1.2.2 Protocol Level 4
            }
            else
            {
                packetWriter.WriteWithLengthPrefix("MQIsdp");
                packetWriter.Write(3); // Protocol Level 3
            }

            byte connectFlags = 0x0;

            if (packet.CleanSession)
            {
                connectFlags |= 0x2;
            }

            if (packet.WillMessage != null)
            {
                connectFlags |= 0x4;
                connectFlags |= (byte)((byte)packet.WillMessage.QualityOfServiceLevel << 3);

                if (packet.WillMessage.Retain)
                {
                    connectFlags |= 0x20;
                }
            }

            if (packet.Password != null && packet.Username == null)
            {
                throw new MqttProtocolViolationException("If the User Name Flag is set to 0, the Password Flag MUST be set to 0 [MQTT-3.1.2-22].");
            }

            if (packet.Password != null)
            {
                connectFlags |= 0x40;
            }

            if (packet.Username != null)
            {
                connectFlags |= 0x80;
            }

            packetWriter.Write(connectFlags);
            packetWriter.Write(packet.KeepAlivePeriod);
            packetWriter.WriteWithLengthPrefix(packet.ClientId);

            if (packet.WillMessage != null)
            {
                packetWriter.WriteWithLengthPrefix(packet.WillMessage.Topic);
                packetWriter.WriteWithLengthPrefix(packet.WillMessage.Payload);
            }

            if (packet.Username != null)
            {
                packetWriter.WriteWithLengthPrefix(packet.Username);
            }

            if (packet.Password != null)
            {
                packetWriter.WriteWithLengthPrefix(packet.Password);
            }

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