MAPPED-ADDRESS, RESPONSE-ADDRESS, CHANGED-ADDRESS, SOURCE-ADDRESS attributes use this format. The Send Keep Alive STUN request also uses an attribute with this format to specify the socket to send the Keep Alive to. 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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |x x x x x x x x| Family | Port | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Address | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Inheritance: STUNAttribute
示例#1
0
        private STUNMessage GetResponse(IPEndPoint receivedEndPoint, STUNMessage stunRequest, bool primary)
        {
            if (stunRequest.Header.MessageType == STUNMessageTypesEnum.BindingRequest)
            {
                STUNMessage stunResponse = new STUNMessage();
                stunResponse.Header.MessageType   = STUNMessageTypesEnum.BindingSuccessResponse;
                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 indicate 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);
        }
示例#2
0
        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);
            }
        }
        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;
            }
        }
示例#4
0
        /// <summary>
        /// Used to get the public IP address and port as seen by the STUN server.
        /// </summary>
        /// <param name="stunServer">A server to send STUN requests to.</param>
        /// <param name="port">The port to use for the request. Defaults to 3478.</param>
        /// <returns>The public IP address and port of the client.</returns>
        public static IPEndPoint GetPublicIPEndPoint(string stunServer, int port = DEFAULT_STUN_PORT)
        {
            try
            {
                logger.LogDebug("STUNClient attempting to determine public IP from " + stunServer + ".");

                using (UdpClient udpClient = new UdpClient(stunServer, port))
                {
                    STUNMessage initMessage      = new STUNMessage(STUNMessageTypesEnum.BindingRequest);
                    byte[]      stunMessageBytes = initMessage.ToByteBuffer(null, false);
                    udpClient.Send(stunMessageBytes, stunMessageBytes.Length);

                    IPEndPoint       publicEndPoint = null;
                    ManualResetEvent gotResponseMRE = new ManualResetEvent(initialState: false);

                    udpClient.BeginReceive((ar) =>
                    {
                        try
                        {
                            IPEndPoint stunResponseEndPoint = null;
                            byte[] stunResponseBuffer       = udpClient.EndReceive(ar, ref stunResponseEndPoint);

                            if (stunResponseBuffer != null && stunResponseBuffer.Length > 0)
                            {
                                logger.LogDebug("STUNClient Response to initial STUN message received from " + stunResponseEndPoint + ".");
                                STUNMessage stunResponse = STUNMessage.ParseSTUNMessage(stunResponseBuffer, stunResponseBuffer.Length);

                                if (stunResponse.Attributes.Count > 0)
                                {
                                    foreach (STUNAttribute stunAttribute in stunResponse.Attributes)
                                    {
                                        if (stunAttribute.AttributeType == STUNAttributeTypesEnum.MappedAddress)
                                        {
                                            STUNAddressAttribute stunAddress = (STUNAddressAttribute)stunAttribute;
                                            publicEndPoint = new IPEndPoint(stunAddress.Address, stunAddress.Port);
                                            logger.LogDebug($"STUNClient Public IP={publicEndPoint.Address} Port={publicEndPoint.Port}.");
                                        }
                                    }
                                }
                            }

                            gotResponseMRE.Set();
                        }
                        catch (Exception recvExcp)
                        {
                            logger.LogWarning("Exception STUNClient Receive. " + recvExcp.Message);
                        }
                    }, state: null);

                    if (gotResponseMRE.WaitOne(STUN_SERVER_RESPONSE_TIMEOUT * 1000))
                    {
                        return(publicEndPoint);
                    }
                    else
                    {
                        logger.LogWarning("STUNClient server response timed out after " + STUN_SERVER_RESPONSE_TIMEOUT + "s.");
                        return(null);
                    }
                }
            }
            catch (Exception excp)
            {
                logger.LogError("Exception STUNClient GetPublicIPAddress. " + excp.Message);
                return(null);
            }
        }
示例#5
0
        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);
            }
        }
        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;
        }