public CoapMessage(Int32 version, CoapType type, CoapCode code, Int32 messageID, byte[] token, List <CoapOption> options, byte[] payload) { this._version = version; this._type = type; this._code = code; this._messageID = messageID; this._token = token; this._options = options; this._payload = payload; }
public static CoapMessage decode(IByteBuffer buf) { byte firstByte = buf.ReadByte(); int version = firstByte >> 6; if (version != 1) { throw new ArgumentException("Invalid version:" + version); } int typeValue = (firstByte >> 4) & 2; CoapType type = (CoapType)typeValue; int tokenLength = firstByte & 0xf; if (tokenLength < 0 || tokenLength > 8) { throw new ArgumentException("Invalid token length:" + tokenLength); } int codeByte = buf.ReadByte(); int codeValue = (codeByte >> 5) * 100; codeValue += codeByte & 0x1F; CoapCode code = (CoapCode)codeValue; int messageID = buf.ReadShort(); if (messageID < 0 || messageID > 65535) { throw new ArgumentException("Invalid messageID value:" + messageID); } byte[] token = new byte[tokenLength]; if (tokenLength > 0) { buf.ReadBytes(token, 0, tokenLength); } int number = 0; List <CoapOption> options = new List <CoapOption>(); while (buf.IsReadable()) { byte nextByte = buf.ReadByte(); if (nextByte == 0xFF) { break; } int delta = ((nextByte >> 4) & 15); if (delta == 13) { delta = (delta << 8 | buf.ReadByte()) - 13; } else if (delta == 14) { delta = (delta << 16 | buf.ReadByte() << 8 | buf.ReadByte()) - 269; } else if (delta < 0 || delta > 14) { throw new ArgumentException("invalid option delta value:" + delta); } number += delta; if (number < 0) { throw new ArgumentException("invalid negative option number:" + number + ", delta:" + delta); } int optionLength = nextByte & 15; if (optionLength == 13) { optionLength = buf.ReadByte() + 13; } else if (optionLength == 14) { optionLength = buf.ReadByte() + 269; } else if (optionLength < 0 || optionLength > 14) { throw new ArgumentException("invalid option length"); } byte[] optionValue = new byte[optionLength]; if (optionLength > 0) { buf.ReadBytes(optionValue, 0, optionLength); } options.Add(new CoapOption(number, optionLength, optionValue)); } byte[] payload = null; if (buf.IsReadable()) { payload = new byte[buf.ReadableBytes]; buf.ReadBytes(payload); } return(new CoapMessage(version, type, code, messageID, token, options, payload)); }
public void PacketReceived(CoapMessage message) { CoapType type = message.CoapType; if ((message.CoapCode == CoapCode.POST || message.CoapCode == CoapCode.PUT) && type != CoapType.ACKNOWLEDGEMENT) { String topic = null; QOS qos = QOS.AT_MOST_ONCE; foreach (CoapOption option in message.Options) { if (option.Number == (int)CoapOptionType.URI_PATH) { topic = Encoding.UTF8.GetString(option.Value); } else if (option.Number == (int)CoapOptionType.ACCEPT) { qos = (QOS)option.Value[option.Value.Length - 1]; } } if (topic == null) { List <CoapOption> options = new List <CoapOption>(); byte[] textBytes = Encoding.UTF8.GetBytes("text/plain"); options.Add(new CoapOption((int)CoapOptionType.CONTENT_FORMAT, textBytes.Length, textBytes)); byte[] nodeIdBytes = Encoding.UTF8.GetBytes(_clientID); options.Add(new CoapOption((int)CoapOptionType.NODE_ID, nodeIdBytes.Length, nodeIdBytes)); CoapMessage ack = new CoapMessage(VERSION, CoapType.ACKNOWLEDGEMENT, CoapCode.BAD_OPTION, message.MessageID, message.Token, options, new byte[0]); _client.Send(ack); return; } byte[] content = message.Payload; _dbInterface.StoreMessage(topic, content, 0); if (_listener != null) { _listener.MessageReceived(MessageType.PUBLISH); } } switch (type) { case CoapType.CONFIRMABLE: { List <CoapOption> options = new List <CoapOption>(); byte[] nodeIdBytes = Encoding.UTF8.GetBytes(_clientID); options.Add(new CoapOption((int)CoapOptionType.NODE_ID, nodeIdBytes.Length, nodeIdBytes)); CoapMessage ack = new CoapMessage(message.Version, CoapType.ACKNOWLEDGEMENT, message.CoapCode, message.MessageID, message.Token, options, new byte[0]); _client.Send(ack); } break; case CoapType.NON_CONFIRMABLE: { _timers.Remove(message.Token); } break; case CoapType.ACKNOWLEDGEMENT: { if (message.CoapCode == CoapCode.GET) { Boolean?observe = null; QOS qos = QOS.AT_MOST_ONCE; foreach (CoapOption option in message.Options) { if (option.Number == (int)CoapOptionType.OBSERVE && option.Value.Length > 0) { if (option.Value[option.Value.Length - 1] == 0x00) { observe = false; } else { observe = true; } } else if (option.Number == (int)CoapOptionType.ACCEPT) { if (option.Value[option.Value.Length - 1] == 0) { qos = QOS.AT_LEAST_ONCE; } } } if (observe.HasValue) { if (!observe.Value) { CoapMessage originalMessage = _timers.Remove(message.Token); if (originalMessage != null) { List <String> topics = new List <String>(); foreach (CoapOption option in originalMessage.Options) { if (option.Number == (int)CoapOptionType.URI_PATH) { topics.Add(Encoding.UTF8.GetString(option.Value)); } } for (int i = 0; i < topics.Count; i++) { _dbInterface.StoreTopic(topics[i], qos); } if (_listener != null) { _listener.MessageReceived(MessageType.SUBACK); } } } else { CoapMessage originalMessage = _timers.Remove(message.Token); if (originalMessage != null) { List <String> topics = new List <String>(); foreach (CoapOption option in originalMessage.Options) { if (option.Number == (int)CoapOptionType.URI_PATH) { topics.Add(Encoding.UTF8.GetString(option.Value)); } } for (int i = 0; i < topics.Count; i++) { _dbInterface.DeleteTopic(topics[i]); } } if (_listener != null) { _listener.MessageReceived(MessageType.UNSUBACK); } } } } else { _timers.Remove(message.Token); if (_listener != null) { _listener.MessageReceived(MessageType.PUBACK); } } } break; case CoapType.RESET: { _timers.Remove(message.Token); } break; } }