/// <summary> /// Parses the Next Option value /// </summary> /// <param name="buffer">The buffer containing the data</param> /// <param name="position">The current position within the buffer</param> /// <param name="remainingData">The amount of data remaining to be parsed</param> /// <returns>The parsed TLV option</returns> public static TLVOptionsData ParseNextOption(byte[] buffer, ref ushort position, ref long remainingData) { TLVOptionsData OptionsData = null; long dataField = 0; byte count = 0; long fieldValue = VarInt.DecodeVarInt(buffer, ref position, out count); WireType wireType = (WireType)(fieldValue & COAP_WIRE_TYPE_MASK); long fieldNumber = fieldValue >> 3; remainingData -= count; switch (wireType) { case WireType.VARINT: { dataField = VarInt.DecodeVarInt(buffer, ref position, out count); OptionsData = new TLVOptionsData(BitConverter.GetBytes(dataField), (byte)fieldNumber); remainingData -= count; break; } case WireType.I64_BIT: { byte[] byaData = new byte[sizeof(Int64)]; Array.Copy(buffer, position, byaData, 0, sizeof(Int64)); OptionsData = new TLVOptionsData(byaData, (byte)fieldNumber); position += sizeof(Int64); remainingData -= sizeof(Int64); break; } case WireType.LENGTH_DELIMITED: { long lengthDelimitedLength = VarInt.DecodeVarInt(buffer, ref position, out count); remainingData -= count; byte[] byaData = new byte[lengthDelimitedLength]; Array.Copy(buffer, position, byaData, 0, lengthDelimitedLength); OptionsData = new TLVOptionsData(byaData, (byte)fieldNumber); position += (ushort)lengthDelimitedLength; remainingData -= (ushort)lengthDelimitedLength; break; } case WireType.I32_BIT: { byte[] byaData = new byte[sizeof(Int32)]; Array.Copy(buffer, position, byaData, 0, sizeof(Int32)); OptionsData = new TLVOptionsData(byaData, (byte)fieldNumber); position += sizeof(Int32); remainingData -= sizeof(Int32); break; } default: { // deprecated or unknown wire type // TODO - what should we do if we encounter one of these? Debug.WriteLine("TLV.ParseNextOption() Warning: Unknown Wire Type detected"); break; } } return(OptionsData); }
/// <summary> /// Parses the content of the buffer passed in and appends the data to the list /// passed in. /// </summary> /// <param name="buffer">the packet data to be parsed</param> /// <param name="TLVList">data structure that will hold the parsed data</param> /// <param name="position">The starting positon of the TLV data</param> // Revision History // MM/DD/YY Who Version Issue# Description // -------- --- ------- ------ ------------------------------------------- // 11/08/16 RCG Added so that this code can be shared with MUSE devices // which have a different start position public static void ParseTLVData(byte[] buffer, ref List <TLVData> TLVList, ushort position) { string TLVId = ""; long length; long remainingData; TLVOptionsData lastOption = null; while (position < buffer.Length) { TLVData data = new TLVData(); byte count; long varIntData = VarInt.DecodeVarInt(buffer, ref position, out count); if (varIntData == VENDOR_DEFINED_TYPE) { // this is a vendor defined TLV // +--------+--------+--------+--------+-------- // | 127 | IANAEN | Type | Length | Value… // +--------+--------+--------+--------+-------- varIntData = VarInt.DecodeVarInt(buffer, ref position, out count); if (varIntData == ITRON_IANAEN) { TLVId = "e1233."; varIntData = VarInt.DecodeVarInt(buffer, ref position, out count); TLVId += varIntData.ToString(CultureInfo.InvariantCulture); } } else { // +--------+--------+-------- // | Type | Length | Value… // +--------+--------+-------- TLVId = varIntData.ToString(CultureInfo.InvariantCulture); } data.TLVID = TLVId; length = VarInt.DecodeVarInt(buffer, ref position, out count); remainingData = length; if (buffer.Length >= position + length) { // There has to be at least 2 bytes of data for us to parse - 1 byte for the tag/wire type and // at least one byte of data do { if (remainingData > 1) { // read and deal with the options lastOption = ParseNextOption(buffer, ref position, ref remainingData); if (lastOption != null) { data.Options.Add(lastOption); } } } while (remainingData > 1 && lastOption != null); TLVList.Add(data); } } }