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); } }
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); } }
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); }