Esempio n. 1
0
        public void Subscribe(Topic[] topics)
        {
            for (int i = 0; i < topics.Length; i++)
            {
                SNQoS realQos = SNQoS.AT_LEAST_ONCE;
                switch (topics[i].Qos)
                {
                case QOS.AT_LEAST_ONCE:
                    realQos = SNQoS.AT_LEAST_ONCE;
                    break;

                case QOS.AT_MOST_ONCE:
                    realQos = SNQoS.AT_MOST_ONCE;
                    break;

                case QOS.EXACTLY_ONCE:
                    realQos = SNQoS.EXACTLY_ONCE;
                    break;
                }

                SNTopic topic;
                if (reverseMappedTopics.ContainsKey(topics[i].Name))
                {
                    topic = new IdentifierTopic(reverseMappedTopics[topics[i].Name], realQos);
                }
                else
                {
                    topic = new FullTopic(topics[i].Name, realQos);
                }

                SNSubscribe subscribe = new SNSubscribe(null, topic, false);
                _timers.Store(subscribe);
                _client.Send(subscribe);
            }
        }
Esempio n. 2
0
        public void Unsubscribe(String[] topics)
        {
            for (int i = 0; i < topics.Length; i++)
            {
                SNQoS   realQos = SNQoS.AT_LEAST_ONCE;
                SNTopic topic;
                if (reverseMappedTopics.ContainsKey(topics[i]))
                {
                    topic = new IdentifierTopic(reverseMappedTopics[topics[i]], realQos);
                }
                else
                {
                    topic = new FullTopic(topics[i], realQos);
                }

                SNUnsubscribe subscribe = new SNUnsubscribe(null, topic);
                _timers.Store(subscribe);
                _client.Send(subscribe);
            }
        }
Esempio n. 3
0
        public void Publish(Topic topic, byte[] content, Boolean retain, Boolean dup)
        {
            SNQoS realQos = SNQoS.AT_LEAST_ONCE;

            switch (topic.Qos)
            {
            case QOS.AT_LEAST_ONCE:
                realQos = SNQoS.AT_LEAST_ONCE;
                break;

            case QOS.AT_MOST_ONCE:
                realQos = SNQoS.AT_MOST_ONCE;
                break;

            case QOS.EXACTLY_ONCE:
                realQos = SNQoS.EXACTLY_ONCE;
                break;
            }

            if (reverseMappedTopics.ContainsKey(topic.Name))
            {
                IdentifierTopic idTopic = new IdentifierTopic(reverseMappedTopics[topic.Name], realQos);
                SNPublish       publish = new SNPublish(null, idTopic, content, dup, retain);
                if (topic.Qos != QOS.AT_MOST_ONCE)
                {
                    _timers.Store(publish);
                }

                _client.Send(publish);
            }
            else
            {
                FullTopic fullTopic = new FullTopic(topic.Name, realQos);
                pendingMessages.Add(new SNPublish(null, fullTopic, content, dup, retain));
                Register register = new Register(0, null, topic.Name);
                _timers.Store(register);
                _client.Send(register);
            }
        }
        public static SNMessage decode(IByteBuffer buf)
        {
            SNMessage message       = null;
            int       currIndex     = buf.ReaderIndex;
            int       messageLength = decodeContentLength(buf);
            int       bytesLeft     = messageLength - (buf.ReaderIndex - currIndex);

            short  typeByte = (short)(0x00FF & (short)buf.ReadByte());
            SNType?type     = null;

            try
            {
                type = (SNType)(int)(typeByte);
            }
            catch (Exception)
            {
                throw new MalformedMessageException("invalid packet type encoding:" + typeByte);
            }

            bytesLeft--;

            switch (type.Value)
            {
            case SNType.ADVERTISE:
                int advertiseGwID     = 0x00FF & (short)buf.ReadByte();
                int advertiseDuration = buf.ReadUnsignedShort();
                message = new Advertise(advertiseGwID, advertiseDuration);
                break;

            case SNType.SEARCHGW:
                int radius = 0x00FF & (short)buf.ReadByte();
                message = new SearchGW((Radius)radius);
                break;

            case SNType.GWINFO:
                int gwInfoGwID = 0x00FF & (short)buf.ReadByte();
                bytesLeft--;
                String gwInfoGwAddress = null;
                if (bytesLeft > 0)
                {
                    byte[] gwInfoGwAddressBytes = new byte[bytesLeft];
                    buf.ReadBytes(gwInfoGwAddressBytes);
                    gwInfoGwAddress = Encoding.UTF8.GetString(gwInfoGwAddressBytes);
                }
                message = new GWInfo(gwInfoGwID, gwInfoGwAddress);
                break;

            case SNType.CONNECT:
                Flags connectFlags = Flags.decode(buf.ReadByte(), type.Value);
                bytesLeft--;
                int protocolID = buf.ReadByte();
                bytesLeft--;
                if (protocolID != SNConnect.MQTT_SN_PROTOCOL_ID)
                {
                    throw new MalformedMessageException("Invalid protocolID " + protocolID);
                }
                int connectDuration = buf.ReadUnsignedShort();
                bytesLeft -= 2;
                if (!ValuesValidator.canRead(buf, bytesLeft))
                {
                    throw new MalformedMessageException(type + ", clientID can't be empty");
                }
                byte[] connectClientIDBytes = new byte[bytesLeft];
                buf.ReadBytes(connectClientIDBytes);
                String connectClientID = Encoding.UTF8.GetString(connectClientIDBytes);
                message = new SNConnect(connectFlags.CleanSession, connectDuration, connectClientID, connectFlags.Will);
                break;

            case SNType.CONNACK:
                ReturnCode connackCode = (ReturnCode)(int)(buf.ReadByte());
                message = new SNConnack(connackCode);
                break;

            case SNType.WILL_TOPIC_REQ:
                message = WILL_TOPIC_REQ;
                break;

            case SNType.WILL_TOPIC:
                Boolean   willTopicRetain = false;
                FullTopic willTopic       = null;
                if (bytesLeft > 0)
                {
                    Flags willTopicFlags = Flags.decode(buf.ReadByte(), type.Value);
                    bytesLeft--;
                    willTopicRetain = willTopicFlags.Retain;
                    if (!ValuesValidator.canRead(buf, bytesLeft))
                    {
                        throw new MalformedMessageException(type + " invalid topic encoding");
                    }
                    byte[] willTopicBytes = new byte[bytesLeft];
                    buf.ReadBytes(willTopicBytes);
                    String willTopicValue = Encoding.UTF8.GetString(willTopicBytes);
                    willTopic = new FullTopic(willTopicValue, willTopicFlags.Qos.Value);
                }
                message = new WillTopic(willTopicRetain, willTopic);
                break;

            case SNType.WILL_MSG_REQ:
                message = WILL_MSG_REQ;
                break;

            case SNType.WILL_MSG:
                if (!ValuesValidator.canRead(buf, bytesLeft))
                {
                    throw new MalformedMessageException(type + " content must not be empty");
                }
                byte[] willMessageContent = new byte[bytesLeft];
                buf.ReadBytes(willMessageContent);
                message = new WillMsg(willMessageContent);
                break;

            case SNType.REGISTER:
                int registerTopicID = buf.ReadUnsignedShort();
                if (!ValuesValidator.validateRegistrationTopicID(registerTopicID))
                {
                    throw new MalformedMessageException(type + " invalid topicID value " + registerTopicID);
                }
                bytesLeft -= 2;
                int registerMessageID = buf.ReadUnsignedShort();
                if (!ValuesValidator.validateMessageID(registerMessageID))
                {
                    throw new MalformedMessageException(type + " invalid messageID " + registerMessageID);
                }
                bytesLeft -= 2;
                if (!ValuesValidator.canRead(buf, bytesLeft))
                {
                    throw new MalformedMessageException(type + " must contain a valid topic");
                }
                byte[] registerTopicBytes = new byte[bytesLeft];
                buf.ReadBytes(registerTopicBytes);
                String registerTopicName = Encoding.UTF8.GetString(registerTopicBytes);
                message = new Register(registerTopicID, registerMessageID, registerTopicName);
                break;

            case SNType.REGACK:
                int regackTopicID = buf.ReadUnsignedShort();
                if (!ValuesValidator.validateRegistrationTopicID(regackTopicID))
                {
                    throw new MalformedMessageException(type + " invalid topicID value " + regackTopicID);
                }
                int regackMessageID = buf.ReadUnsignedShort();
                if (!ValuesValidator.validateMessageID(regackMessageID))
                {
                    throw new MalformedMessageException(type + " invalid messageID " + regackMessageID);
                }
                ReturnCode regackCode = (ReturnCode)(int)(buf.ReadByte());
                message = new Regack(regackTopicID, regackMessageID, regackCode);
                break;

            case SNType.PUBLISH:
                Flags publishFlags = Flags.decode(buf.ReadByte(), type.Value);
                bytesLeft--;
                int publishTopicID = buf.ReadUnsignedShort();
                bytesLeft -= 2;
                int publishMessageID = buf.ReadUnsignedShort();
                bytesLeft -= 2;
                if (publishFlags.Qos.Value != SNQoS.AT_MOST_ONCE && publishMessageID == 0)
                {
                    throw new MalformedMessageException("invalid PUBLISH QoS-0 messageID:" + publishMessageID);
                }
                SNTopic publishTopic = null;
                if (publishFlags.TopicType == TopicType.SHORT)
                {
                    publishTopic = new ShortTopic(publishTopicID.ToString(), publishFlags.Qos.Value);
                }
                else
                {
                    if (!ValuesValidator.validateTopicID(publishTopicID))
                    {
                        throw new MalformedMessageException(type + " invalid topicID value " + publishTopicID);
                    }
                    publishTopic = new IdentifierTopic(publishTopicID, publishFlags.Qos.Value);
                }

                byte[] data = new byte[bytesLeft];
                if (bytesLeft > 0)
                {
                    buf.ReadBytes(data);
                }

                message = new SNPublish(publishMessageID, publishTopic, data, publishFlags.Dup, publishFlags.Retain);
                break;

            case SNType.PUBACK:
                int pubackTopicID = buf.ReadUnsignedShort();
                if (!ValuesValidator.validateTopicID(pubackTopicID))
                {
                    throw new MalformedMessageException(type + " invalid topicID value " + pubackTopicID);
                }
                int pubackMessageID = buf.ReadUnsignedShort();
                if (!ValuesValidator.validateMessageID(pubackMessageID))
                {
                    throw new MalformedMessageException(type + " invalid messageID " + pubackMessageID);
                }
                ReturnCode pubackCode = (ReturnCode)(int)(buf.ReadByte());
                message = new SNPuback(pubackTopicID, pubackMessageID, pubackCode);
                break;

            case SNType.PUBREC:
                int pubrecMessageID = buf.ReadUnsignedShort();
                if (!ValuesValidator.validateMessageID(pubrecMessageID))
                {
                    throw new MalformedMessageException(type + " invalid messageID " + pubrecMessageID);
                }
                message = new SNPubrec(pubrecMessageID);
                break;

            case SNType.PUBREL:
                int pubrelMessageID = buf.ReadUnsignedShort();
                if (!ValuesValidator.validateMessageID(pubrelMessageID))
                {
                    throw new MalformedMessageException(type + " invalid messageID " + pubrelMessageID);
                }
                message = new SNPubrel(pubrelMessageID);
                break;

            case SNType.PUBCOMP:
                int pubcompMessageID = buf.ReadUnsignedShort();
                if (!ValuesValidator.validateMessageID(pubcompMessageID))
                {
                    throw new MalformedMessageException(type + " invalid messageID " + pubcompMessageID);
                }
                message = new SNPubcomp(pubcompMessageID);
                break;

            case SNType.SUBSCRIBE:
                Flags subscribeFlags = Flags.decode(buf.ReadByte(), type.Value);
                bytesLeft--;
                int subscribeMessageID = buf.ReadUnsignedShort();
                if (subscribeMessageID == 0)
                {
                    throw new MalformedMessageException(type + " invalid messageID " + subscribeMessageID);
                }
                bytesLeft -= 2;
                if (!ValuesValidator.canRead(buf, bytesLeft) || bytesLeft < 2)
                {
                    throw new MalformedMessageException(type + " invalid topic encoding");
                }
                byte[] subscribeTopicBytes = new byte[bytesLeft];
                buf.ReadBytes(subscribeTopicBytes);
                SNTopic subscribeTopic = null;
                switch (subscribeFlags.TopicType)
                {
                case TopicType.NAMED:
                    String subscribeTopicName = Encoding.UTF8.GetString(subscribeTopicBytes);
                    subscribeTopic = new FullTopic(subscribeTopicName, subscribeFlags.Qos.Value);
                    break;

                case TopicType.ID:
                    int subscribeTopicID = BitConverter.ToInt16(subscribeTopicBytes, 0);
                    if (!ValuesValidator.validateTopicID(subscribeTopicID))
                    {
                        throw new MalformedMessageException(type + " invalid topicID value " + subscribeTopicID);
                    }
                    subscribeTopic = new IdentifierTopic(subscribeTopicID, subscribeFlags.Qos.Value);
                    break;

                case TopicType.SHORT:
                    String subscribeTopicShortName = Encoding.UTF8.GetString(subscribeTopicBytes);
                    subscribeTopic = new ShortTopic(subscribeTopicShortName, subscribeFlags.Qos.Value);
                    break;
                }
                message = new SNSubscribe(subscribeMessageID, subscribeTopic, subscribeFlags.Dup);
                break;

            case SNType.SUBACK:
                Flags subackFlags   = Flags.decode(buf.ReadByte(), type.Value);
                int   subackTopicID = buf.ReadUnsignedShort();
                if (!ValuesValidator.validateRegistrationTopicID(subackTopicID))
                {
                    throw new MalformedMessageException(type + " invalid topicID value " + subackTopicID);
                }
                int subackMessageID = buf.ReadUnsignedShort();
                if (!ValuesValidator.validateMessageID(subackMessageID))
                {
                    throw new MalformedMessageException(type + " invalid messageID " + subackMessageID);
                }
                ReturnCode subackCode = (ReturnCode)(int)(buf.ReadByte());
                message = new SNSuback(subackTopicID, subackMessageID, subackCode, subackFlags.Qos.Value);
                break;

            case SNType.UNSUBSCRIBE:
                Flags unsubscribeFlags = Flags.decode(buf.ReadByte(), type.Value);
                bytesLeft--;
                int unsubscribeMessageID = buf.ReadUnsignedShort();
                if (!ValuesValidator.validateMessageID(unsubscribeMessageID))
                {
                    throw new MalformedMessageException(type + " invalid messageID " + unsubscribeMessageID);
                }
                bytesLeft -= 2;
                byte[] unsubscribeTopicBytes = new byte[bytesLeft];
                buf.ReadBytes(unsubscribeTopicBytes);
                SNTopic unsubscribeTopic = null;
                switch (unsubscribeFlags.TopicType)
                {
                case TopicType.NAMED:
                    String unsubscribeTopicName = Encoding.UTF8.GetString(unsubscribeTopicBytes);
                    unsubscribeTopic = new FullTopic(unsubscribeTopicName, unsubscribeFlags.Qos.Value);
                    break;

                case TopicType.ID:
                    int unsubscribeTopicID = BitConverter.ToInt16(unsubscribeTopicBytes, 0);
                    if (!ValuesValidator.validateTopicID(unsubscribeTopicID))
                    {
                        throw new MalformedMessageException(type + " invalid topicID value " + unsubscribeTopicID);
                    }
                    unsubscribeTopic = new IdentifierTopic(unsubscribeTopicID, unsubscribeFlags.Qos.Value);
                    break;

                case TopicType.SHORT:
                    String unsubscribeTopicShortName = Encoding.UTF8.GetString(unsubscribeTopicBytes);
                    unsubscribeTopic = new ShortTopic(unsubscribeTopicShortName, unsubscribeFlags.Qos.Value);
                    break;
                }
                message = new SNUnsubscribe(unsubscribeMessageID, unsubscribeTopic);
                break;

            case SNType.UNSUBACK:
                int unsubackMessageID = buf.ReadUnsignedShort();
                if (!ValuesValidator.validateMessageID(unsubackMessageID))
                {
                    throw new MalformedMessageException(type + " invalid messageID " + unsubackMessageID);
                }
                message = new SNUnsuback(unsubackMessageID);
                break;

            case SNType.PINGREQ:
                String pingreqClientID = null;
                if (bytesLeft > 0)
                {
                    byte[] pingreqClientIDValue = new byte[bytesLeft];
                    buf.ReadBytes(pingreqClientIDValue);
                    pingreqClientID = Encoding.UTF8.GetString(pingreqClientIDValue);
                }
                message = new SNPingreq(pingreqClientID);
                break;

            case SNType.PINGRESP:
                message = PING_RESP;
                break;

            case SNType.DISCONNECT:
                int duration = 0;
                if (bytesLeft > 0)
                {
                    duration = buf.ReadUnsignedShort();
                }
                message = new SNDisconnect(duration);
                break;

            case SNType.WILL_TOPIC_UPD:
                FullTopic willTopicUpdTopic     = null;
                Boolean   willTopicUpdateRetain = false;
                if (bytesLeft > 0)
                {
                    Flags willTopicUpdFlags = Flags.decode(buf.ReadByte(), type.Value);
                    willTopicUpdateRetain = willTopicUpdFlags.Retain;
                    bytesLeft--;
                    byte[] willTopicUpdTopicBytes = new byte[bytesLeft];
                    buf.ReadBytes(willTopicUpdTopicBytes);
                    String willTopicUpdTopicValue = Encoding.UTF8.GetString(willTopicUpdTopicBytes);
                    willTopicUpdTopic = new FullTopic(willTopicUpdTopicValue, willTopicUpdFlags.Qos.Value);
                }
                message = new WillTopicUpd(willTopicUpdateRetain, willTopicUpdTopic);
                break;

            case SNType.WILL_MSG_UPD:
                if (!ValuesValidator.canRead(buf, bytesLeft))
                {
                    throw new MalformedMessageException(type + " must contain content data");
                }
                byte[] willMsgUpdContent = new byte[bytesLeft];
                buf.ReadBytes(willMsgUpdContent);
                message = new WillMsgUpd(willMsgUpdContent);
                break;

            case SNType.WILL_TOPIC_RESP:
                ReturnCode willTopicRespCode = (ReturnCode)(int)buf.ReadByte();
                message = new WillTopicResp(willTopicRespCode);
                break;

            case SNType.WILL_MSG_RESP:
                ReturnCode willMsgRespCode = (ReturnCode)(int)buf.ReadByte();
                message = new WillMsgResp(willMsgRespCode);
                break;

            case SNType.ENCAPSULATED:
                Controls control = Controls.decode(buf.ReadByte());
                bytesLeft--;
                byte[] wirelessNodeIDBytes = new byte[bytesLeft];
                buf.ReadBytes(wirelessNodeIDBytes);
                String    wirelessNodeID      = Encoding.UTF8.GetString(wirelessNodeIDBytes);
                SNMessage encapsulatedMessage = SNParser.decode(buf);
                message = new Encapsulated(control.Radius, wirelessNodeID, encapsulatedMessage);
                break;
            }

            if (buf.IsReadable())
            {
                throw new MalformedMessageException("not all bytes have been read from buffer:" + buf.ReadableBytes);
            }

            if (messageLength != message.getLength())
            {
                throw new MalformedMessageException(String.Format("Invalid length. Encoded: %d, actual: %d", messageLength, message.getLength()));
            }

            return(message);
        }