public static List <STUNAttribute> ParseMessageAttributes(byte[] buffer, int startIndex, int endIndex)
{
if (buffer != null && buffer.Length > startIndex && buffer.Length >= endIndex)
{
List <STUNAttribute> attributes = new List <STUNAttribute>();
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 = NetConvert.DoReverseEndian(stunAttributeType);
stunAttributeLength = NetConvert.DoReverseEndian(stunAttributeLength);
}
if (stunAttributeLength > 0)
{
if (stunAttributeLength + startIndex + 4 > endIndex)
{
logger.LogWarning(
"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);
}
}
STUNAttributeTypesEnum attributeType =
STUNAttributeTypes.GetSTUNAttributeTypeForId(stunAttributeType);
STUNAttribute attribute = null;
if (attributeType == STUNAttributeTypesEnum.ChangeRequest)
{
attribute = new STUNChangeRequestAttribute(stunAttributeValue);
}
else if (attributeType == STUNAttributeTypesEnum.MappedAddress)
{
attribute = new STUNAddressAttribute(stunAttributeValue);
}
else if (attributeType == STUNAttributeTypesEnum.ErrorCode)
{
attribute = new STUNErrorCodeAttribute(stunAttributeValue);
}
else if (attributeType == STUNAttributeTypesEnum.XORMappedAddress ||
attributeType == STUNAttributeTypesEnum.XORPeerAddress ||
attributeType == STUNAttributeTypesEnum.XORRelayedAddress)
{
attribute = new STUNXORAddressAttribute(attributeType, stunAttributeValue);
}
else
{
attribute = new STUNAttribute(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);
}
}