public static List<STUNv2Attribute> ParseMessageAttributes(byte[] buffer, int startIndex, int endIndex)
{
if (buffer != null && buffer.Length > startIndex && buffer.Length >= endIndex)
{
List<STUNv2Attribute> attributes = new List<STUNv2Attribute>();
int startAttIndex = startIndex;
while (startAttIndex < endIndex)
{
UInt16 stunAttributeType = BitConverter.ToUInt16(buffer, startAttIndex);
UInt16 stunAttributeLength = BitConverter.ToUInt16(buffer, startAttIndex + 2);
byte[] stunAttributeValue = null;
if (BitConverter.IsLittleEndian)
{
stunAttributeType = Utility.ReverseEndian(stunAttributeType);
stunAttributeLength = Utility.ReverseEndian(stunAttributeLength);
}
if (stunAttributeLength > 0)
{
if (stunAttributeLength + startIndex + 4 > endIndex)
{
logger.Warn("The attribute length on a STUN parameter was greater than the available number of bytes.");
}
else
{
stunAttributeValue = new byte[stunAttributeLength];
Buffer.BlockCopy(buffer, startAttIndex + 4, stunAttributeValue, 0, stunAttributeLength);
}
}
STUNv2AttributeTypesEnum attributeType = STUNv2AttributeTypes.GetSTUNAttributeTypeForId(stunAttributeType);
STUNv2Attribute attribute = null;
if (attributeType == STUNv2AttributeTypesEnum.ChangeRequest)
{
attribute = new STUNv2ChangeRequestAttribute(stunAttributeValue);
}
else if (attributeType == STUNv2AttributeTypesEnum.MappedAddress)
{
attribute = new STUNv2AddressAttribute(stunAttributeValue);
}
else if (attributeType == STUNv2AttributeTypesEnum.ErrorCode)
{
attribute = new STUNv2ErrorCodeAttribute(stunAttributeValue);
}
else if (attributeType == STUNv2AttributeTypesEnum.XORMappedAddress || attributeType == STUNv2AttributeTypesEnum.XORPeerAddress || attributeType == STUNv2AttributeTypesEnum.XORRelayedAddress)
{
attribute = new STUNv2XORAddressAttribute(attributeType, stunAttributeValue);
}
else
{
attribute = new STUNv2Attribute(attributeType, stunAttributeValue);
}
attributes.Add(attribute);
// Attributes start on 32 bit word boundaries so where an attribute length is not a multiple of 4 it gets padded.
int padding = (stunAttributeLength % 4 != 0) ? 4 - (stunAttributeLength % 4) : 0;
startAttIndex = startAttIndex + 4 + stunAttributeLength + padding;
}
return attributes;
}
else
{
return null;
}
}