private STUNMessage GetResponse(IPEndPoint receivedEndPoint, STUNMessage stunRequest, bool primary)
        {
            if (stunRequest.Header.MessageType == STUNMessageTypesEnum.BindingRequest)
            {
                STUNMessage stunResponse = new STUNMessage();
                stunResponse.Header.MessageType   = STUNMessageTypesEnum.BindingResponse;
                stunResponse.Header.TransactionId = stunRequest.Header.TransactionId;

                // Add MappedAddress attribute to indicate the socket the request was received from.
                STUNAddressAttribute mappedAddressAtt = new STUNAddressAttribute(STUNAttributeTypesEnum.MappedAddress, receivedEndPoint.Port, receivedEndPoint.Address);
                stunResponse.Attributes.Add(mappedAddressAtt);

                // Add SourceAddress attribute to indicate the socket used to send the response.
                if (primary)
                {
                    STUNAddressAttribute sourceAddressAtt = new STUNAddressAttribute(STUNAttributeTypesEnum.SourceAddress, m_primaryEndPoint.Port, m_primaryEndPoint.Address);
                    stunResponse.Attributes.Add(sourceAddressAtt);
                }
                else
                {
                    STUNAddressAttribute sourceAddressAtt = new STUNAddressAttribute(STUNAttributeTypesEnum.SourceAddress, m_secondaryEndPoint.Port, m_secondaryEndPoint.Address);
                    stunResponse.Attributes.Add(sourceAddressAtt);
                }

                // Add ChangedAddress attribute to inidcate the servers alternative socket.
                if (primary)
                {
                    STUNAddressAttribute changedAddressAtt = new STUNAddressAttribute(STUNAttributeTypesEnum.ChangedAddress, m_secondaryEndPoint.Port, m_secondaryEndPoint.Address);
                    stunResponse.Attributes.Add(changedAddressAtt);
                }
                else
                {
                    STUNAddressAttribute changedAddressAtt = new STUNAddressAttribute(STUNAttributeTypesEnum.ChangedAddress, m_primaryEndPoint.Port, m_primaryEndPoint.Address);
                    stunResponse.Attributes.Add(changedAddressAtt);
                }

                //Console.WriteLine(stunResponse.ToString());

                //byte[] stunResponseBuffer = stunResponse.ToByteBuffer();

                return(stunResponse);
            }

            return(null);
        }
        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   = Utility.ReverseEndian(stunAttributeType);
                        stunAttributeLength = Utility.ReverseEndian(stunAttributeLength);
                    }

                    if (stunAttributeLength > 0)
                    {
                        if (stunAttributeType == (int)STUNAttributeTypesEnum.Username && stunAttributeLength > buffer.Length - startIndex - 4)
                        {
                            // Received some STUN messages where the username is shorter than the claimed length.
                            int realLength = buffer.Length - startIndex - 4;
                            stunAttributeValue = new byte[realLength];
                            Buffer.BlockCopy(buffer, startIndex + 4, stunAttributeValue, 0, realLength);
                        }
                        else
                        {
                            stunAttributeValue = new byte[stunAttributeLength];
                            Buffer.BlockCopy(buffer, startIndex + 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
                    {
                        attribute = new STUNAttribute(attributeType, stunAttributeLength, stunAttributeValue);
                    }

                    attributes.Add(attribute);

                    startAttIndex = startAttIndex + 4 + stunAttributeLength;
                }

                return(attributes);
            }
            else
            {
                return(null);
            }
        }