public void ProcessConnack(ConnackCode code, Boolean sessionPresent)
        {
            // CANCEL CONNECT TIMER
            MessageResendTimer <MQMessage> timer = _timers.ConnectTimer;

            _timers.StopConnectTimer();

            // CHECK CODE , IF OK THEN MOVE TO CONNECTED AND NOTIFY NETWORK SESSION
            if (code == ConnackCode.ACCEPTED)
            {
                SetState(ConnectionState.CONNECTION_ESTABLISHED);

                if (timer != null)
                {
                    Connect connect = (Connect)timer.Message;
                    if (connect.CleanSession)
                    {
                        clearAccountTopics();
                    }
                }

                _timers.StartPingTimer();
            }
            else
            {
                _timers.StopAllTimers();
                _client.Shutdown();
                SetState(ConnectionState.CONNECTION_FAILED);
            }
        }
 public Connack(Boolean sessionPresent, ConnackCode returnCode)
 {
     this._sessionPresent = sessionPresent;
     this._returnCode     = returnCode;
 }
Ejemplo n.º 3
0
        /// <exception cref="MalformedMessageException">Exception is thrown in case of invalid packet format</exception>
        public static MQMessage Decode(IByteBuffer buf)
        {
            MQMessage header = null;

            byte fixedHeader = buf.ReadByte();

            LengthDetails length = DecodeLength(buf);

            MessageType type = (MessageType)((fixedHeader >> 4) & 0xf);

            switch (type)
            {
            case MessageType.CONNECT:

                Byte[] nameValue = new byte[buf.ReadUnsignedShort()];
                buf.ReadBytes(nameValue, 0, nameValue.Length);
                String name = Encoding.UTF8.GetString(nameValue);
                if (!name.Equals(Connect.PROTOCOL_NAME))
                {
                    throw new MalformedMessageException("CONNECT, protocol-name set to " + name);
                }

                Byte protocolLevel = buf.ReadByte();
                Byte contentFlags  = buf.ReadByte();

                Boolean userNameFlag = (((contentFlags >> 7) & 1) == 1) ? true : false;
                Boolean userPassFlag = (((contentFlags >> 6) & 1) == 1) ? true : false;
                Boolean willRetain   = (((contentFlags >> 5) & 1) == 1) ? true : false;

                Int32 QOSValue = ((contentFlags & 0x1f) >> 3) & 3;
                QOS   willQos  = (QOS)QOSValue;
                if (!Enum.IsDefined(typeof(QOS), QOSValue))
                {
                    throw new MalformedMessageException("CONNECT, will QoS set to " + willQos);
                }
                Boolean willFlag = (((contentFlags >> 2) & 1) == 1) ? true : false;

                if (willQos != QOS.AT_MOST_ONCE && !willFlag)
                {
                    throw new MalformedMessageException("CONNECT, will QoS set to " + willQos + ", willFlag not set");
                }

                if (willRetain && !willFlag)
                {
                    throw new MalformedMessageException("CONNECT, will retain set, willFlag not set");
                }

                Boolean cleanSession = (((contentFlags >> 1) & 1) == 1) ? true : false;

                Boolean reservedFlag = ((contentFlags & 1) == 1) ? true : false;
                if (reservedFlag)
                {
                    throw new MalformedMessageException("CONNECT, reserved flag set to true");
                }

                int keepalive = buf.ReadUnsignedShort();

                Byte[] clientIdValue = new byte[buf.ReadUnsignedShort()];
                buf.ReadBytes(clientIdValue, 0, clientIdValue.Length);
                String clientID = Encoding.UTF8.GetString(clientIdValue);
                if (!StringVerifier.verify(clientID))
                {
                    throw new MalformedMessageException("ClientID contains restricted characters: U+0000, U+D000-U+DFFF");
                }

                String willTopic   = null;
                Byte[] willMessage = null;
                String username    = null;
                String password    = null;

                Will will = null;
                if (willFlag)
                {
                    if (buf.ReadableBytes < 2)
                    {
                        throw new MalformedMessageException("Invalid encoding will/username/password");
                    }

                    byte[] willTopicValue = new byte[buf.ReadUnsignedShort()];
                    if (buf.ReadableBytes < willTopicValue.Length)
                    {
                        throw new MalformedMessageException("Invalid encoding will/username/password");
                    }

                    buf.ReadBytes(willTopicValue, 0, willTopicValue.Length);

                    willTopic = Encoding.UTF8.GetString(willTopicValue);
                    if (!StringVerifier.verify(willTopic))
                    {
                        throw new MalformedMessageException("WillTopic contains one or more restricted characters: U+0000, U+D000-U+DFFF");
                    }

                    if (buf.ReadableBytes < 2)
                    {
                        throw new MalformedMessageException("Invalid encoding will/username/password");
                    }

                    willMessage = new byte[buf.ReadUnsignedShort()];
                    if (buf.ReadableBytes < willMessage.Length)
                    {
                        throw new MalformedMessageException("Invalid encoding will/username/password");
                    }

                    buf.ReadBytes(willMessage, 0, willMessage.Length);
                    if (willTopic.Length == 0)
                    {
                        throw new MalformedMessageException("invalid will encoding");
                    }
                    will = new Will(new Topic(willTopic, willQos), willMessage, willRetain);
                    if (!will.IsValid())
                    {
                        throw new MalformedMessageException("invalid will encoding");
                    }
                }

                if (userNameFlag)
                {
                    if (buf.ReadableBytes < 2)
                    {
                        throw new MalformedMessageException("Invalid encoding will/username/password");
                    }

                    byte[] userNameValue = new byte[buf.ReadUnsignedShort()];
                    if (buf.ReadableBytes < userNameValue.Length)
                    {
                        throw new MalformedMessageException("Invalid encoding will/username/password");
                    }

                    buf.ReadBytes(userNameValue, 0, userNameValue.Length);
                    username = Encoding.UTF8.GetString(userNameValue);
                    if (!StringVerifier.verify(username))
                    {
                        throw new MalformedMessageException("Username contains one or more restricted characters: U+0000, U+D000-U+DFFF");
                    }
                }

                if (userPassFlag)
                {
                    if (buf.ReadableBytes < 2)
                    {
                        throw new MalformedMessageException("Invalid encoding will/username/password");
                    }

                    byte[] userPassValue = new byte[buf.ReadUnsignedShort()];
                    if (buf.ReadableBytes < userPassValue.Length)
                    {
                        throw new MalformedMessageException("Invalid encoding will/username/password");
                    }

                    buf.ReadBytes(userPassValue, 0, userPassValue.Length);
                    password = Encoding.UTF8.GetString(userPassValue);
                    if (!StringVerifier.verify(password))
                    {
                        throw new MalformedMessageException("Password contains one or more restricted characters: U+0000, U+D000-U+DFFF");
                    }
                }

                if (buf.ReadableBytes > 0)
                {
                    throw new MalformedMessageException("Invalid encoding will/username/password");
                }

                Connect connect = new Connect(username, password, clientID, cleanSession, keepalive, will);
                if (protocolLevel != 4)
                {
                    connect.ProtocolLevel = protocolLevel;
                }
                header = connect;
                break;

            case MessageType.CONNACK:
                byte sessionPresentValue = buf.ReadByte();
                if (sessionPresentValue != 0 && sessionPresentValue != 1)
                {
                    throw new MalformedMessageException("CONNACK, session-present set to " + (sessionPresentValue & 0xff));
                }

                Boolean isPresent = sessionPresentValue == 1 ? true : false;

                Int32       connackByte = ((Int32)buf.ReadByte()) & 0xFF;
                ConnackCode connackCode = (ConnackCode)connackByte;
                if (!Enum.IsDefined(typeof(ConnackCode), connackByte))
                {
                    throw new MalformedMessageException("Invalid connack code: " + connackByte);
                }
                header = new Connack(isPresent, connackCode);
                break;

            case MessageType.PUBLISH:
                int dataLength = length.Length;
                fixedHeader &= 0xf;

                Boolean dup = (((fixedHeader >> 3) & 1) == 1) ? true : false;

                QOSValue = (fixedHeader & 0x07) >> 1;
                QOS qos = (QOS)QOSValue;
                if (!Enum.IsDefined(typeof(QOS), (byte)QOSValue))
                {
                    throw new MalformedMessageException("invalid QoS value");
                }
                if (dup && qos == QOS.AT_MOST_ONCE)
                {
                    throw new MalformedMessageException("PUBLISH, QoS-0 dup flag present");
                }

                Boolean retain = ((fixedHeader & 1) == 1) ? true : false;

                byte[] topicNameValue = new byte[buf.ReadUnsignedShort()];
                buf.ReadBytes(topicNameValue, 0, topicNameValue.Length);
                String topicName = Encoding.UTF8.GetString(topicNameValue);
                if (!StringVerifier.verify(topicName))
                {
                    throw new MalformedMessageException("Publish-topic contains one or more restricted characters: U+0000, U+D000-U+DFFF");
                }
                dataLength -= topicName.Length + 2;

                Int32?packetID = null;
                if (qos != QOS.AT_MOST_ONCE)
                {
                    packetID = buf.ReadUnsignedShort();
                    if (packetID < 0 || packetID > 65535)
                    {
                        throw new MalformedMessageException("Invalid PUBLISH packetID encoding");
                    }
                    dataLength -= 2;
                }
                byte[] data = new byte[dataLength];
                if (dataLength > 0)
                {
                    buf.ReadBytes(data, 0, data.Length);
                }
                header = new Publish(packetID, new Topic(topicName, qos), data, retain, dup);
                break;

            case MessageType.PUBACK:
                header = new Puback(buf.ReadUnsignedShort());
                break;

            case MessageType.PUBREC:
                header = new Pubrec(buf.ReadUnsignedShort());
                break;

            case MessageType.PUBREL:
                header = new Pubrel(buf.ReadUnsignedShort());
                break;

            case MessageType.PUBCOMP:
                header = new Pubcomp(buf.ReadUnsignedShort());
                break;

            case MessageType.SUBSCRIBE:
                Int32        subID         = buf.ReadUnsignedShort();
                List <Topic> subscriptions = new List <Topic>();
                while (buf.IsReadable())
                {
                    byte[] value = new byte[buf.ReadUnsignedShort()];
                    buf.ReadBytes(value, 0, value.Length);
                    QOSValue = buf.ReadByte();
                    QOS requestedQos = (QOS)QOSValue;
                    if (!Enum.IsDefined(typeof(QOS), QOSValue))
                    {
                        throw new MalformedMessageException("Subscribe qos must be in range from 0 to 2: " + requestedQos);
                    }
                    String topic = Encoding.UTF8.GetString(value);
                    if (!StringVerifier.verify(topic))
                    {
                        throw new MalformedMessageException("Subscribe topic contains one or more restricted characters: U+0000, U+D000-U+DFFF");
                    }
                    Topic subscription = new Topic(topic, requestedQos);
                    subscriptions.Add(subscription);
                }
                if (subscriptions.Count == 0)
                {
                    throw new MalformedMessageException("Subscribe with 0 topics");
                }

                header = new Subscribe(subID, subscriptions.ToArray());
                break;

            case MessageType.SUBACK:
                Int32             subackID    = buf.ReadUnsignedShort();
                List <SubackCode> subackCodes = new List <SubackCode>();
                while (buf.IsReadable())
                {
                    Int32      subackByte = ((Int32)buf.ReadByte()) & 0xFF;
                    SubackCode subackCode = (SubackCode)subackByte;
                    if (!Enum.IsDefined(typeof(SubackCode), subackByte))
                    {
                        throw new MalformedMessageException("Invalid suback code: " + subackByte);
                    }
                    subackCodes.Add(subackCode);
                }
                if (subackCodes.Count == 0)
                {
                    throw new MalformedMessageException("Suback with 0 return-codes");
                }

                header = new Suback(subackID, subackCodes);
                break;

            case MessageType.UNSUBSCRIBE:
                Int32         unsubID           = buf.ReadUnsignedShort();
                List <String> unsubscribeTopics = new List <String>();
                while (buf.IsReadable())
                {
                    byte[] value = new byte[buf.ReadUnsignedShort()];
                    buf.ReadBytes(value, 0, value.Length);
                    String topic = Encoding.UTF8.GetString(value);
                    if (!StringVerifier.verify(topic))
                    {
                        throw new MalformedMessageException("Unsubscribe topic contains one or more restricted characters: U+0000, U+D000-U+DFFF");
                    }
                    unsubscribeTopics.Add(topic);
                }
                if (unsubscribeTopics.Count == 0)
                {
                    throw new MalformedMessageException("Unsubscribe with 0 topics");
                }
                header = new Unsubscribe(unsubID, unsubscribeTopics.ToArray());
                break;

            case MessageType.UNSUBACK:
                header = new Unsuback(buf.ReadUnsignedShort());
                break;

            case MessageType.PINGREQ:
                header = new Pingreq();
                break;

            case MessageType.PINGRESP:
                header = new Pingresp();
                break;

            case MessageType.DISCONNECT:
                header = new Disconnect();
                break;

            default:
                throw new MalformedMessageException("Invalid header type: " + type);
            }

            if (buf.IsReadable())
            {
                throw new MalformedMessageException("unexpected bytes in content");
            }

            if (length.Length != header.GetLength())
            {
                throw new MalformedMessageException("Invalid length. Encoded: " + length.Length + ", actual: " + header.GetLength());
            }

            return(header);
        }