/*
*
* Code derived and adapted from the Jitsi client side STUN framework.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.restcomm.media.stun.messages.attributes;
import org.restcomm.media.stun.StunException;
/**
* After the header are 0 or more attributes. Each attribute is TLV
* encoded, with a 16 bit type, 16 bit length, and variable value:
*
* 0 1 2 3 <br/>
* 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 <br/>
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ <br/>
* | Type | Length | <br/>
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ <br/>
* | Value .... <br/>
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ <br/>
*<br/>
* The following types are defined:<br/>
*<br/>
* STUN attributes:<br/>
* 0x0001: MAPPED-ADDRESS <br/>
* 0x0002: RESPONSE-ADDRESS <br/>
* 0x0003: CHANGE-REQUEST <br/>
* 0x0004: SOURCE-ADDRESS <br/>
* 0x0005: CHANGED-ADDRESS <br/>
* 0x0006: USERNAME <br/>
* 0x0007: PASSWORD <br/>
* 0x0008: MESSAGE-INTEGRITY <br/>
* 0x0009: ERROR-CODE <br/>
* 0x000a: UNKNOWN-ATTRIBUTES <br/>
* 0x000b: REFLECTED-FROM <br/>
* 0x0014: REALM <br/>
* 0x0015: NONCE <br/>
* 0x0020: XOR-MAPPED-ADDRESS <br/>
* 0x8022: SOFTWARE <br/>
* 0x8023: ALTERNATE-SERVER <br/>
* 0x8028: FINGERPRINT <br/>
* <br/>
* TURN attributes:<br/>
* 0x000C: CHANNEL-NUMBER <br/>
* 0x000D: LIFETIME <br/>
* 0x0012: XOR-PEER-ADDRESS <br/>
* 0x0013: DATA <br/>
* 0x0016: XOR-RELAYED-ADDRESS <br/>
* 0x0018: EVEN-PORT <br/>
* 0x0019: REQUESTED-TRANSPORT <br/>
* 0x001A: DONT-FRAGMENT <br/>
* 0x0022: RESERVATION-TOKEN <br/>
*
* ICE attributes:<br/>
* 0x0024: PRIORITY <br/>
* 0x0025: USE-CANDIDATE <br/>
* 0x8029: ICE-CONTROLLED <br/>
* 0x802A: ICE-CONTROLLING <br/>
*
*/
public abstract class StunAttribute {
/* STUN attributes */
/**
* Mapped address attribute.
*/
public static final char MAPPED_ADDRESS = 0x0001;
/**
* Response address attribute.
*/
public static final char RESPONSE_ADDRESS = 0x0002;
/**
* Change request attribute.
*/
public static final char CHANGE_REQUEST = 0x0003;
/**
* Source address attribute.
*/
public static final char SOURCE_ADDRESS = 0x0004;
/**
* Changed address attribute.
*/
public static final char CHANGED_ADDRESS = 0x0005;
/**
* Username attribute.
*/
public static final char USERNAME = 0x0006;
/**
* Password attribute.
*/
public static final char PASSWORD = 0x0007;
/**
* Message integrity attribute.
*/
public static final char MESSAGE_INTEGRITY = 0x0008;
/**
* Error code attribute.
*/
public static final char ERROR_CODE = 0x0009;
/**
* Unknown attributes attribute.
*/
public static final char UNKNOWN_ATTRIBUTES = 0x000a;
/**
* Reflected from attribute.
*/
public static final char REFLECTED_FROM = 0x000b;
/**
* Realm attribute.
*/
public static final char REALM = 0x0014;
/**
* Nonce attribute.
*/
public static final char NONCE = 0x0015;
/**
* XOR Mapped address attribute.
*/
public static final char XOR_MAPPED_ADDRESS = 0x0020;
/**
* XOR only attribute.
*/
public static final char XOR_ONLY = 0x0021;
/**
* Software attribute.
*/
public static final char SOFTWARE = 0x8022;
/**
* Alternate server attribute.
*/
public static final char ALTERNATE_SERVER = 0x8023;
/**
* Fingerprint attribute.
*/
public static final char FINGERPRINT = 0x8028;
/**
* Unknown optional attribute.
*/
public static final char UNKNOWN_OPTIONAL_ATTRIBUTE = 0x8000;
/* TURN attributes */
/**
* Channel number attribute.
*/
public static final char CHANNEL_NUMBER = 0x000c;
/**
* Lifetime attribute.
*/
public static final char LIFETIME = 0x000d;
/**
* XOR peer address attribute.
*/
public static final char XOR_PEER_ADDRESS = 0x0012;
/**
* Data attribute.
*/
public static final char DATA = 0x0013;
/**
* XOR relayed address attribute.
*/
public static final char XOR_RELAYED_ADDRESS = 0x0016;
/**
* Even port attribute.
*/
public static final char EVEN_PORT = 0x0018;
/**
* Requested transport attribute.
*/
public static final char REQUESTED_TRANSPORT = 0x0019;
/**
* Don't fragment attribute.
*/
public static final char DONT_FRAGMENT = 0x001a;
/**
* Reservation token attribute.
*/
public static final char RESERVATION_TOKEN = 0x0022;
/* Old TURN attributes */
/**
* Magic cookie attribute.
*/
public static final char MAGIC_COOKIE = 0x000f;
/**
* Destination address attribute.
*/
public static final char DESTINATION_ADDRESS = 0x0011;
/**
* Destination address attribute.
*/
public static final char REMOTE_ADDRESS = 0x0012;
/* ICE attributes */
/**
* Priority attribute.
*/
public static final char PRIORITY = 0x0024;
/**
* Use candidate attribute.
*/
public static final char USE_CANDIDATE = 0x0025;
/**
* ICE controlled attribute.
*/
public static final char ICE_CONTROLLED = 0x8029;
/**
* ICE controlling attribute.
*/
public static final char ICE_CONTROLLING = 0x802a;
/**
* The type of the attribute.
*/
protected char attributeType = 0;
/**
* The size of an atribute header in bytes = len(TYPE) + len(LENGTH) = 4
*/
public static final char HEADER_LENGTH = 4;
/**
* For attributes that have arriving in incoming messages, this fiels
* contains their original location in the binary array so that we could
* later more easily verify attributes like MESSAGE-INTEGRITY.
*/
private int locationInMessage = -1;
/**
* Creates an empty STUN message attribute.
*
* @param attributeType
* the type of the attribute.
*/
protected StunAttribute(char attributeType) {
setAttributeType(attributeType);
}
/**
* Returns the length of this attribute's body.
*
* @return the length of this attribute's value.
*/
public abstract char getDataLength();
/**
* Returns the human readable name of this attribute. Attribute names do not
* really matter from the protocol point of view. They are only used for
* debugging and readability.
*
* @return this attribute's name.
*/
public abstract String getName();
/**
* Returns the attribute's type.
*
* @return the type of this attribute.
*/
public char getAttributeType() {
return attributeType;
}
/**
* Sets the attribute's type.
*
* @param type
* the new type of this attribute
*/
protected void setAttributeType(char type) {
this.attributeType = type;
}
/**
* Compares two STUN Attributes. Two attributes are considered equal when
* they have the same type length and value.
*
* @param other
* the object to compare this attribute with.
*
* @return true if the attributes are equal and false otherwise.
*/
public abstract boolean equals(Object other);
/**
* Returns a binary representation of this attribute.
*
* @return a binary representation of this attribute.
*/
public abstract byte[] encode();
/**
* For attributes that have arriving in incoming messages, this method
* stores their original location in the binary array so that we could later
* more easily verify attributes like MESSAGE-INTEGRITY.
*
* @param index
* the original location of this attribute in the datagram we got
* off the wire
*/
public void setLocationInMessage(int index) {
this.locationInMessage = index;
}
/**
* For attributes that have arriving in incoming messages, this method
* returns their original location in the binary array so that we could
* later more easily verify attributes like MESSAGE-INTEGRITY.
*
* @return the original location of this attribute in the datagram we got
* off the wire or -1 if this is not an incoming
* {@link StunAttribute}
*/
public int getLocationInMessage() {
return this.locationInMessage;
}
/**
* Sets this attribute's fields according to attributeValue array.
*
* @param data
* a binary array containing this attribute's field values and
* NOT containing the attribute header.
* @param offset
* the position where attribute values begin (most often offset
* is equal to the index of the first byte after length)
* @param length
* the length of the binary array.
*
* @throws StunException
* if attrubteValue contains invalid data.
*/
protected abstract void decodeAttributeBody(byte[] data, char offset,
char length) throws StunException;
}