/** * Compares two STUN Attributes. Attributeas are considered equal when their * type, length, and all data are the same. * * @param obj the object to compare this attribute with. * @return true if the attributes are equal and false otherwise. */ public override bool Equals(Object obj) { if (!(obj is UnknownAttributesAttribute) || obj == null) { return(false); } if (obj == this) { return(true); } UnknownAttributesAttribute att = (UnknownAttributesAttribute)obj; if (att.GetAttributeType() != GetAttributeType() || att.GetDataLength() != GetDataLength() || !unknownAttributes.Equals(att.unknownAttributes) ) { return(false); } return(true); }
/** * Creates a binding error response according to the specified error code * and unknown attributes. * * @param errorCode the error code to encapsulate in this message * @param reasonPhrase a human readable description of the error * @param unknownAttributes a char[] array containing the ids of one or more * attributes that had not been recognized. * @throws StunException INVALID_ARGUMENTS if one or more of the given * parameters had an invalid value. * * @return a binding error response message containing an error code and a * UNKNOWN-ATTRIBUTES header */ private static Response CreateBindingErrorResponse(int errorCode, String reasonPhrase, int[] unknownAttributes) { Response bindingErrorResponse = new Response(); bindingErrorResponse.SetMessageType(Message.BINDING_ERROR_RESPONSE); //init attributes UnknownAttributesAttribute unknownAttributesAttribute = null; ErrorCodeAttribute errorCodeAttribute = AttributeFactory.CreateErrorCodeAttribute(errorCode, reasonPhrase); bindingErrorResponse.AddAttribute(errorCodeAttribute); if (unknownAttributes != null) { unknownAttributesAttribute = AttributeFactory. CreateUnknownAttributesAttribute(); for (int i = 0; i < unknownAttributes.Length; i++) { unknownAttributesAttribute.AddAttributeID(unknownAttributes[i]); } bindingErrorResponse.AddAttribute(unknownAttributesAttribute); } return(bindingErrorResponse); }
//------------------------------------ UNKNOWN ATTRIBUTES ---------------------- /** * Creates an empty UnknownAttributesAttribute. * @return the newly created UnknownAttributesAttribute */ public static UnknownAttributesAttribute CreateUnknownAttributesAttribute() { UnknownAttributesAttribute attribute = new UnknownAttributesAttribute(); return(attribute); }
//------------------------------------ UNKNOWN ATTRIBUTES ---------------------- /** * Creates an empty UnknownAttributesAttribute. * @return the newly created UnknownAttributesAttribute */ public static UnknownAttributesAttribute CreateUnknownAttributesAttribute() { UnknownAttributesAttribute attribute = new UnknownAttributesAttribute(); return attribute; }
/** * Decodes the specified binary array and returns the corresponding * attribute object. * @param bytes the binary array that should be decoded. * @param offset the index where the message starts. * @param length the number of bytes that the message is long. * @return An object representing the attribute encoded in bytes or null if * the attribute was not recognized. * @throws StunException if bytes does is not a valid STUN attribute. */ public static Attribute decode(byte[] bytes, int offset, int length) { if(bytes == null || bytes.Length < Attribute.HEADER_LENGTH) throw new StunException(StunException.ILLEGAL_ARGUMENT, "Could not decode the specified binary array."); //Discover attribute type int attributeTypec = (int)(((bytes[offset]<<8)&0xff00)|(bytes[offset + 1] & 0xff)); int attributeType = (int) attributeTypec; int attributeLengthc = (int)(((bytes[offset + 2]<<8)&0xff00)|(bytes[offset + 3]&0xff)); int attributeLength = (int) attributeLengthc; if(attributeLength > bytes.Length - offset ) { throw new StunException(StunException.ILLEGAL_ARGUMENT, "The indicated attribute length ("+attributeLength+") " +"does not match the length of the passed binary array"); } Attribute decodedAttribute = null; switch(attributeType) { case Attribute.CHANGE_REQUEST: decodedAttribute = new ChangeRequestAttribute(); break; case Attribute.CHANGED_ADDRESS: decodedAttribute = new ChangedAddressAttribute(); break; case Attribute.MAPPED_ADDRESS: decodedAttribute = new MappedAddressAttribute(); break; case Attribute.ERROR_CODE: decodedAttribute = new ErrorCodeAttribute(); break; case Attribute.MESSAGE_INTEGRITY: throw new StunException( "The MESSAGE-INTEGRITY Attribute is not yet implemented."); case Attribute.PASSWORD: throw new StunException( "The PASSWORD Attribute is not yet implemented."); case Attribute.REFLECTED_FROM: decodedAttribute = new ReflectedFromAttribute(); break; case Attribute.RESPONSE_ADDRESS: decodedAttribute = new ResponseAddressAttribute(); break; case Attribute.SOURCE_ADDRESS: decodedAttribute = new SourceAddressAttribute(); break; case Attribute.UNKNOWN_ATTRIBUTES: decodedAttribute = new UnknownAttributesAttribute(); break; case Attribute.USERNAME: throw new StunException( "The USERNAME Attribute is not yet implemented."); //According to rfc3489 we should silently ignore unknown attributes. default: decodedAttribute = new UnknownAttributesAttribute(); break; //return null; } decodedAttribute.SetAttributeType(attributeType); decodedAttribute.DecodeAttributeBody(bytes, (Attribute.HEADER_LENGTH + offset), attributeLength); return decodedAttribute; }
/** * Decodes the specified binary array and returns the corresponding * attribute object. * @param bytes the binary array that should be decoded. * @param offset the index where the message starts. * @param length the number of bytes that the message is long. * @return An object representing the attribute encoded in bytes or null if * the attribute was not recognized. * @throws StunException if bytes does is not a valid STUN attribute. */ public static Attribute decode(byte[] bytes, int offset, int length) { if (bytes == null || bytes.Length < Attribute.HEADER_LENGTH) { throw new StunException(StunException.ILLEGAL_ARGUMENT, "Could not decode the specified binary array."); } //Discover attribute type int attributeTypec = (int)(((bytes[offset] << 8) & 0xff00) | (bytes[offset + 1] & 0xff)); int attributeType = (int)attributeTypec; int attributeLengthc = (int)(((bytes[offset + 2] << 8) & 0xff00) | (bytes[offset + 3] & 0xff)); int attributeLength = (int)attributeLengthc; if (attributeLength > bytes.Length - offset) { throw new StunException(StunException.ILLEGAL_ARGUMENT, "The indicated attribute length (" + attributeLength + ") " + "does not match the length of the passed binary array"); } Attribute decodedAttribute = null; switch (attributeType) { case Attribute.CHANGE_REQUEST: decodedAttribute = new ChangeRequestAttribute(); break; case Attribute.CHANGED_ADDRESS: decodedAttribute = new ChangedAddressAttribute(); break; case Attribute.MAPPED_ADDRESS: decodedAttribute = new MappedAddressAttribute(); break; case Attribute.ERROR_CODE: decodedAttribute = new ErrorCodeAttribute(); break; case Attribute.MESSAGE_INTEGRITY: throw new StunException( "The MESSAGE-INTEGRITY Attribute is not yet implemented."); case Attribute.PASSWORD: throw new StunException( "The PASSWORD Attribute is not yet implemented."); case Attribute.REFLECTED_FROM: decodedAttribute = new ReflectedFromAttribute(); break; case Attribute.RESPONSE_ADDRESS: decodedAttribute = new ResponseAddressAttribute(); break; case Attribute.SOURCE_ADDRESS: decodedAttribute = new SourceAddressAttribute(); break; case Attribute.UNKNOWN_ATTRIBUTES: decodedAttribute = new UnknownAttributesAttribute(); break; case Attribute.USERNAME: throw new StunException( "The USERNAME Attribute is not yet implemented."); //According to rfc3489 we should silently ignore unknown attributes. default: decodedAttribute = new UnknownAttributesAttribute(); break; //return null; } decodedAttribute.SetAttributeType(attributeType); decodedAttribute.DecodeAttributeBody(bytes, (Attribute.HEADER_LENGTH + offset), attributeLength); return(decodedAttribute); }