private static void EncodeFbnsConnectPacket(FbnsConnectPacket packet, DataWriter writer)
        {
            var  payload     = packet.Payload;
            uint payloadSize = payload?.Length ?? 0;

            byte[] protocolNameBytes = EncodeStringInUtf8(packet.ProtocolName);
            // variableHeaderwriterferSize = 2 bytes length + ProtocolName bytes + 4 bytes
            // 4 bytes are reserved for: 1 byte ProtocolLevel, 1 byte ConnectFlags, 2 byte KeepAlive
            uint variableHeaderwriterferSize = (uint)(STRING_SIZE_LENGTH + protocolNameBytes.Length + 4);
            uint variablePartSize            = variableHeaderwriterferSize + payloadSize;

            // MQTT message format from: http://public.dhe.ibm.com/software/dw/webservices/ws-mqtt/MQTT_V3.1_Protocol_Specific.pdf
            writer.WriteByte((byte)((int)packet.PacketType << 4)); // Write packet type
            WriteVariableLengthInt(writer, variablePartSize);      // Write remaining length

            // Variable part
            writer.WriteUInt16((ushort)protocolNameBytes.Length);
            writer.WriteBytes(protocolNameBytes);
            writer.WriteByte(packet.ProtocolLevel);
            writer.WriteByte(packet.ConnectFlags);
            writer.WriteUInt16(packet.KeepAliveInSeconds);

            if (payload != null)
            {
                writer.WriteBuffer(payload);
            }
        }
Exemple #2
0
        private static Packet DecodePacketInternal(DataReader reader, int packetSignature, ref uint remainingLength)
        {
            if (Signatures.IsPublish(packetSignature))
            {
                var qualityOfService =
                    (QualityOfService)((packetSignature >> 1) &
                                       0x3);  // take bits #1 and #2 ONLY and convert them into QoS value
                if (qualityOfService == QualityOfService.Reserved)
                {
                    throw new DecoderException(
                              $"Unexpected QoS value of {(int)qualityOfService} for {PacketType.PUBLISH} packet.");
                }

                bool duplicate = (packetSignature & 0x8) == 0x8; // test bit#3
                bool retain    = (packetSignature & 0x1) != 0;   // test bit#0
                var  packet    = new PublishPacket(qualityOfService, duplicate, retain);
                DecodePublishPacket(reader, packet, ref remainingLength);
                return(packet);
            }

            switch (packetSignature & 240)  // We don't care about flags for these packets
            {
            case Signatures.Subscribe& 240:
                var subscribePacket = new SubscribePacket();
                DecodePacketIdVariableHeader(reader, subscribePacket, ref remainingLength);
                DecodeSubscribePayload(reader, subscribePacket, ref remainingLength);
                return(subscribePacket);

            case Signatures.Connect:
                var connectPacket = new FbnsConnectPacket();
                DecodeConnectPacket(reader, connectPacket, ref remainingLength);
                return(connectPacket);

            case Signatures.ConnAck:
                var connAckPacket = new FbnsConnAckPacket();
                DecodeConnAckPacket(reader, connAckPacket, ref remainingLength);
                return(connAckPacket);

            case Signatures.SubAck:
                var subAckPacket = new SubAckPacket();
                DecodePacketIdVariableHeader(reader, subAckPacket, ref remainingLength);
                DecodeSubAckPayload(reader, subAckPacket, ref remainingLength);
                return(subAckPacket);

            case Signatures.Unsubscribe& 240:
                var unsubscribePacket = new UnsubscribePacket();
                DecodePacketIdVariableHeader(reader, unsubscribePacket, ref remainingLength);
                DecodeUnsubscribePayload(reader, unsubscribePacket, ref remainingLength);
                return(unsubscribePacket);

            case Signatures.PingResp:
                return(PingRespPacket.Instance);

            case Signatures.PubAck:
                var pubAckPacket = new PubAckPacket();
                DecodePacketIdVariableHeader(reader, pubAckPacket, ref remainingLength);
                return(pubAckPacket);

            default: return(null);
                //default:
                //    throw new DecoderException($"Packet type {packetSignature} not supported");
            }
        }
Exemple #3
0
        static void DecodeConnectPacket(DataReader reader, FbnsConnectPacket packet, ref uint remainingLength)
        {
            string protocolName = DecodeString(reader, ref remainingLength);

            // if (!PROTOCOL_NAME.Equals(protocolName, StringComparison.Ordinal))
            // {
            //     throw new DecoderException($"Unexpected protocol name. Expected: {PROTOCOL_NAME}. Actual: {protocolName}");
            // }
            packet.ProtocolName = protocolName;

            DecreaseRemainingLength(ref remainingLength, 1);
            packet.ProtocolLevel = reader.ReadByte();

            // if (packet.ProtocolLevel != Util.ProtocolLevel)
            // {
            //     var connAckPacket = new ConnAckPacket();
            //     connAckPacket.ReturnCode = ConnectReturnCode.RefusedUnacceptableProtocolVersion;
            //     context.WriteAndFlushAsync(connAckPacket);
            //     throw new DecoderException($"Unexpected protocol level. Expected: {Util.ProtocolLevel}. Actual: {packet.ProtocolLevel}");
            // }

            DecreaseRemainingLength(ref remainingLength, 1);
            int connectFlags = reader.ReadByte();

            packet.CleanSession = (connectFlags & 0x02) == 0x02;

            bool hasWill = (connectFlags & 0x04) == 0x04;

            if (hasWill)
            {
                packet.HasWill              = true;
                packet.WillRetain           = (connectFlags & 0x20) == 0x20;
                packet.WillQualityOfService = (QualityOfService)((connectFlags & 0x18) >> 3);
                if (packet.WillQualityOfService == QualityOfService.Reserved)
                {
                    throw new DecoderException($"[MQTT-3.1.2-14] Unexpected Will QoS value of {(int)packet.WillQualityOfService}.");
                }
                packet.WillTopicName = string.Empty;
            }
            else if ((connectFlags & 0x38) != 0) // bits 3,4,5 [MQTT-3.1.2-11]
            {
                throw new DecoderException("[MQTT-3.1.2-11]");
            }

            packet.HasUsername = (connectFlags & 0x80) == 0x80;
            packet.HasPassword = (connectFlags & 0x40) == 0x40;
            if (packet.HasPassword && !packet.HasUsername)
            {
                throw new DecoderException("[MQTT-3.1.2-22]");
            }
            if ((connectFlags & 0x1) != 0) // [MQTT-3.1.2-3]
            {
                throw new DecoderException("[MQTT-3.1.2-3]");
            }

            packet.KeepAliveInSeconds = DecodeUnsignedShort(reader, ref remainingLength);

            string clientId = DecodeString(reader, ref remainingLength);

            if (string.IsNullOrEmpty(clientId))
            {
                throw new DecoderException("Client identifier is required.");
            }
            packet.ClientId = clientId;

            if (hasWill)
            {
                packet.WillTopicName = DecodeString(reader, ref remainingLength);
                var willMessageLength = DecodeUnsignedShort(reader, ref remainingLength);
                DecreaseRemainingLength(ref remainingLength, willMessageLength);
                packet.WillMessage = reader.ReadBuffer(willMessageLength);
            }

            if (packet.HasUsername)
            {
                packet.Username = DecodeString(reader, ref remainingLength);
            }

            if (packet.HasPassword)
            {
                packet.Password = DecodeString(reader, ref remainingLength);
            }
        }