/// <summary> /// Parses STUN message from raw data packet. /// </summary> /// <param name="data">Raw STUN message.</param> internal void Parse(byte[] data) { /* RFC 3489 11.1. * All STUN messages consist of a 20 byte header: * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | STUN Message Type | Message Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Transaction ID +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | The message length is the count, in bytes, of the size of the | message, not including the 20 byte header. */ if (data.Length < 20) { throw new ArgumentException("Invalid STUN message value !"); } int offset = 0; //--- message header -------------------------------------------------- // STUN Message Type int messageType = (data[offset++] << 8 | data[offset++]); if (messageType == (int)StunMessageType.BindingErrorResponse) { m_Type = StunMessageType.BindingErrorResponse; } else if (messageType == (int)StunMessageType.BindingRequest) { m_Type = StunMessageType.BindingRequest; } else if (messageType == (int)StunMessageType.BindingResponse) { m_Type = StunMessageType.BindingResponse; } else if (messageType == (int)StunMessageType.SharedSecretErrorResponse) { m_Type = StunMessageType.SharedSecretErrorResponse; } else if (messageType == (int)StunMessageType.SharedSecretRequest) { m_Type = StunMessageType.SharedSecretRequest; } else if (messageType == (int)StunMessageType.SharedSecretResponse) { m_Type = StunMessageType.SharedSecretResponse; } else { throw new ArgumentException("Invalid STUN message type value !"); } // Message Length int messageLength = (data[offset++] << 8 | data[offset++]); // Transaction ID byte[] guid = new byte[16]; Array.Copy(data, offset, guid, 0, 16); m_pTransactionID = new Guid(guid); offset += 16; //--- Message attributes --------------------------------------------- while ((offset - 20) < messageLength) { ParseAttribute(data, ref offset); } }
static Boolean IsResponse(StunMessageType type) { return(((UInt16)type & 0x0100) != 0); }