/// <summary> /// Parse the CoAP message stream and extract details of the token /// </summary> /// <param name="coapMsgStream">The CoAP message stream that contains the token length and value</param> /// <param name="startIndex">The index to start looking for the value</param> /// <param name="extraInfo">Not used</param> /// <returns>The next index from where next set of information can be extracted from the message stream</returns> public int Parse(byte[] coapMsgStream, int startIndex, UInt16 extraInfo) { if (coapMsgStream == null || coapMsgStream.Length == 0 || startIndex < 0) { return(startIndex); //do nothing } if (coapMsgStream.Length < AbstractCoAPMessage.HEADER_LENGTH) { throw new CoAPFormatException("Invalid CoAP message stream"); } if (startIndex >= coapMsgStream.Length) { throw new ArgumentException("Start index beyond message stream length"); } //First get the token length...its there in bits 4-7 starting from left of first byte this.Length = (byte)(coapMsgStream[startIndex] & 0x0F); if (this.Length > 0) { //Search for token value int tokenValueStartIndex = 4; //Token value follows after first 4 bytes if (coapMsgStream.Length < (4 + this.Length)) { throw new CoAPFormatException("Invalid message stream. Token not present in the stream despite non-zero length"); } byte[] tokenValue = new byte[this.Length]; Array.Copy(coapMsgStream, tokenValueStartIndex, tokenValue, 0, this.Length); tokenValue = AbstractNetworkUtils.FromNetworkByteOrder(tokenValue); this.Value = tokenValue; } //We have parsed the token length...this finishes the byte...the index should move to next byte return(startIndex + 1); }
/// <summary> /// Parse the CoAP message stream and extract message Id (in network byte order) /// </summary> /// <param name="coapMsgStream">The CoAP message stream that contains the token length and value</param> /// <param name="startIndex">The index to start looking for the value</param> /// <param name="extraInfo">Not used</param> /// <returns>The next index from where next set of information can be extracted from the message stream</returns> public int Parse(byte[] coapMsgStream, int startIndex, UInt16 extraInfo) { if (coapMsgStream == null || coapMsgStream.Length == 0 || startIndex < 0) { return(startIndex); //do nothing } if (coapMsgStream.Length < AbstractCoAPMessage.HEADER_LENGTH) { throw new CoAPFormatException("Invalid CoAP message stream"); } if (startIndex >= coapMsgStream.Length) { throw new ArgumentException("Start index beyond message stream length"); } //We read two bytes... byte[] mid = { coapMsgStream[startIndex], coapMsgStream[startIndex + 1] }; //We received them in network byte order...fix the order based on the platform mid = AbstractNetworkUtils.FromNetworkByteOrder(mid); Value = AbstractByteUtils.ToUInt16(mid); return(startIndex + 2); }
/// <summary> /// Create a header option by parsing the coap data stream /// </summary> /// <param name="coapStream">The CoAP message stream that contains the option</param> /// <param name="startIndex">The index to start looking for the option</param> /// <param name="previousOptionNumber">The previous option number in the sequence of options</param> /// <returns>The next index from where next set of information can be extracted from the message stream</returns> public int Parse(byte[] coapStream, int startIndex, UInt16 previousOptionNumber) { if (coapStream == null || coapStream.Length < startIndex || startIndex < AbstractCoAPMessage.HEADER_LENGTH) { throw new ArgumentNullException("CoAP stream is null or start index is invalid"); } int nextIndex = startIndex; byte optionDelta = (byte)((coapStream[nextIndex] & 0xF0) >> 4); byte optionLength = (byte)(coapStream[nextIndex] & 0x0F); UInt16 optionStreamSizeInBytes = 1; //Calculate option number if (optionDelta < 13) { this.Number = (UInt16)(optionDelta + previousOptionNumber); } else if (optionDelta == 13) { this.Number = (UInt16)((UInt16)coapStream[++nextIndex] + 13 + previousOptionNumber); optionStreamSizeInBytes += 1; } else if (optionDelta == 14) { byte[] optionDeltaEx = new byte[] { coapStream[++nextIndex], coapStream[++nextIndex] }; optionDeltaEx = AbstractNetworkUtils.FromNetworkByteOrder(optionDeltaEx); this.Number = (UInt16)(AbstractByteUtils.ToUInt16(optionDeltaEx) + (UInt16)269 + previousOptionNumber); optionStreamSizeInBytes += 2; } else if (optionDelta == 15) { throw new CoAPFormatException("Option delta cannot contain payload marker value"); } //Calculate option value length if (optionLength < 13) { ValueSizeInBytes = optionLength; } else if (optionLength == 13) { ValueSizeInBytes = (UInt16)(coapStream[++nextIndex] + 13); optionStreamSizeInBytes += 1; } else if (optionLength == 14) { byte[] optionLengthEx = new byte[] { coapStream[++nextIndex], coapStream[++nextIndex] }; optionLengthEx = AbstractNetworkUtils.FromNetworkByteOrder(optionLengthEx); ValueSizeInBytes = (UInt16)(AbstractByteUtils.ToUInt16(optionLengthEx) + (UInt16)269); optionStreamSizeInBytes += 2; } else if (optionLength == 15) { throw new CoAPFormatException("Option length cannot be 0x0F. This is a reserved value"); } //Check if option is of type uint or is empty if ((this.NeedsByteOrdering(this.Number) && optionLength == 0) || this.IsEmpty()) { //this means that the value of the option is zero or this is an empty option Value = null; } else if (ValueSizeInBytes > 0) //normal processing { //Get option Value Value = new byte[ValueSizeInBytes]; Array.Copy(coapStream, ++nextIndex, Value, 0, ValueSizeInBytes); if (this.NeedsByteOrdering(this.Number)) { Value = AbstractNetworkUtils.FromNetworkByteOrder(Value); } optionStreamSizeInBytes += ValueSizeInBytes; } return(startIndex + optionStreamSizeInBytes); }