/*
*
* 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 java.io.UnsupportedEncodingException;
import java.lang.reflect.UndeclaredThrowableException;
import org.restcomm.media.network.deprecated.TransportAddress;
import org.restcomm.media.stun.StunException;
import org.restcomm.media.stun.messages.attributes.address.ChangedAddressAttribute;
import org.restcomm.media.stun.messages.attributes.address.DestinationAddressAttribute;
import org.restcomm.media.stun.messages.attributes.address.ReflectedFromAttribute;
import org.restcomm.media.stun.messages.attributes.address.ResponseAddressAttribute;
import org.restcomm.media.stun.messages.attributes.address.SourceAddressAttribute;
import org.restcomm.media.stun.messages.attributes.address.XorMappedAddressAttribute;
import org.restcomm.media.stun.messages.attributes.address.XorPeerAddressAttribute;
import org.restcomm.media.stun.messages.attributes.address.XorRelayedAddressAttribute;
import org.restcomm.media.stun.messages.attributes.control.ControlledAttribute;
import org.restcomm.media.stun.messages.attributes.control.ControllingAttribute;
import org.restcomm.media.stun.messages.attributes.data.DataAttribute;
import org.restcomm.media.stun.messages.attributes.general.ChangeRequestAttribute;
import org.restcomm.media.stun.messages.attributes.general.ChannelNumberAttribute;
import org.restcomm.media.stun.messages.attributes.general.ErrorCodeAttribute;
import org.restcomm.media.stun.messages.attributes.general.EvenPortAttribute;
import org.restcomm.media.stun.messages.attributes.general.FingerprintAttribute;
import org.restcomm.media.stun.messages.attributes.general.LifetimeAttribute;
import org.restcomm.media.stun.messages.attributes.general.MagicCookieAttribute;
import org.restcomm.media.stun.messages.attributes.general.MappedAddressAttribute;
import org.restcomm.media.stun.messages.attributes.general.MessageIntegrityAttribute;
import org.restcomm.media.stun.messages.attributes.general.NonceAttribute;
import org.restcomm.media.stun.messages.attributes.general.PriorityAttribute;
import org.restcomm.media.stun.messages.attributes.general.RealmAttribute;
import org.restcomm.media.stun.messages.attributes.general.RequestedTransportAttribute;
import org.restcomm.media.stun.messages.attributes.general.ReservationTokenAttribute;
import org.restcomm.media.stun.messages.attributes.general.SoftwareAttribute;
import org.restcomm.media.stun.messages.attributes.general.UnknownAttributesAttribute;
import org.restcomm.media.stun.messages.attributes.general.UseCandidateAttribute;
import org.restcomm.media.stun.messages.attributes.general.UsernameAttribute;
/**
* Factory that provides STUN/TURN/ICE attributes.
*/
public class StunAttributeFactory {
/**
* Creates a ChangeRequestAttribute with "false" values for the changeIP and
* changePort flags.
*
* @return the newly created ChangeRequestAttribute.
*/
public static ChangeRequestAttribute createChangeRequestAttribute() {
return createChangeRequestAttribute(false, false);
}
/**
* Creates a ChangeRequestAttribute with the specified flag values.
*
* @param changeIP
* the value of the changeIP flag.
* @param changePort
* the value of the changePort flag.
* @return the newly created ChangeRequestAttribute.
*/
public static ChangeRequestAttribute createChangeRequestAttribute(
boolean changeIP, boolean changePort) {
ChangeRequestAttribute attribute = new ChangeRequestAttribute();
attribute.setAddressChanging(changeIP);
attribute.setPortChanging(changePort);
return attribute;
}
/**
* Creates a changedAddressAttribute of the specified type and with the
* specified address and port
*
* @param address
* the address value of the address attribute
* @return the newly created address attribute.
*/
public static ChangedAddressAttribute createChangedAddressAttribute(
TransportAddress address) {
ChangedAddressAttribute attribute = new ChangedAddressAttribute();
attribute.setAddress(address);
return attribute;
}
/**
* Creates an ErrorCodeAttribute with the specified error class and number
* and a default reason phrase.
*
* @param errorClass
* a valid error class.
* @param errorNumber
* a valid error number.
* @return the newly created attribute.
* @throws StunException
* if the error class or number have invalid values according to
* rfc3489.
*/
public static ErrorCodeAttribute createErrorCodeAttribute(byte errorClass,
byte errorNumber) throws StunException {
return createErrorCodeAttribute(errorClass, errorNumber, null);
}
/**
* Creates an ErrorCodeAttribute with the specified error class, number and
* reason phrase.
*
* @param errorClass
* a valid error class.
* @param errorNumber
* a valid error number.
* @param reasonPhrase
* a human readable reason phrase. A null reason phrase would be
* replaced (if possible) by a default one as defined byte the
* rfc3489.
* @return the newly created attribute.
* @throws StunException
* if the error class or number have invalid values according to
* rfc3489.
*/
public static ErrorCodeAttribute createErrorCodeAttribute(byte errorClass,
byte errorNumber, String reasonPhrase) throws StunException {
ErrorCodeAttribute attribute = new ErrorCodeAttribute();
attribute.setErrorClass(errorClass);
attribute.setErrorNumber(errorNumber);
attribute.setReasonPhrase(reasonPhrase == null ? ErrorCodeAttribute
.getDefaultReasonPhrase(attribute.getErrorCode())
: reasonPhrase);
return attribute;
}
/**
* Creates an ErrorCodeAttribute with the specified error code and a default
* reason phrase.
*
* @param errorCode
* a valid error code.
* @return the newly created attribute.
* @throws StunException
* if errorCode is not a valid error code as defined by rfc3489
*/
public static ErrorCodeAttribute createErrorCodeAttribute(char errorCode)
throws StunException {
return createErrorCodeAttribute(errorCode, null);
}
/**
* Creates an ErrorCodeAttribute with the specified error code and reason
* phrase.
*
* @param errorCode
* a valid error code.
* @param reasonPhrase
* a human readable reason phrase. A null reason phrase would be
* replaced (if possible) by a default one as defined byte the
* rfc3489.
*
* @return the newly created attribute.
* @throws IllegalArgumentException
* if errorCode is not a valid error code as defined by rfc3489
*/
public static ErrorCodeAttribute createErrorCodeAttribute(char errorCode,
String reasonPhrase) throws IllegalArgumentException {
ErrorCodeAttribute attribute = new ErrorCodeAttribute();
attribute.setErrorCode(errorCode);
attribute.setReasonPhrase(reasonPhrase == null ? ErrorCodeAttribute
.getDefaultReasonPhrase(attribute.getErrorCode())
: reasonPhrase);
return attribute;
}
/**
* Creates a MappedAddressAttribute of the specified type and with the
* specified address and port
*
* @param address
* the address value of the address attribute
* @return the newly created address attribute.
*/
public static MappedAddressAttribute createMappedAddressAttribute(
TransportAddress address) {
MappedAddressAttribute attribute = new MappedAddressAttribute();
attribute.setAddress(address);
return attribute;
}
/**
* Creates a ReflectedFromAddressAttribute of the specified type and with
* the specified address and port
*
* @param address
* the address value of the address attribute
* @return the newly created address attribute.
*/
public static ReflectedFromAttribute createReflectedFromAttribute(
TransportAddress address) {
ReflectedFromAttribute attribute = new ReflectedFromAttribute();
attribute.setAddress(address);
return attribute;
}
/**
* Creates a ResponseFromAddressAttribute of the specified type and with the
* specified address and port
*
* @param address
* the address value of the address attribute
* @return the newly created address attribute.
*/
public static ResponseAddressAttribute createResponseAddressAttribute(
TransportAddress address) {
ResponseAddressAttribute attribute = new ResponseAddressAttribute();
attribute.setAddress(address);
return attribute;
}
/**
* Creates a SourceFromAddressAttribute of the specified type and with the
* specified address and port
*
* @param address
* the address value of the address attribute
* @return the newly created address attribute.
*/
public static SourceAddressAttribute createSourceAddressAttribute(
TransportAddress address) {
SourceAddressAttribute attribute = new SourceAddressAttribute();
attribute.setAddress(address);
return attribute;
}
/**
* Creates an empty UnknownAttributesAttribute.
*
* @return the newly created UnknownAttributesAttribute
*/
public static UnknownAttributesAttribute createUnknownAttributesAttribute() {
UnknownAttributesAttribute attribute = new UnknownAttributesAttribute();
return attribute;
}
/**
* Creates a XorRelayedAddressAttribute of the specified type and with the
* specified address and port.
*
* @param address
* the address value of the address attribute
* @param tranID
* the ID of the transaction that we will be using for the XOR
* mask.
*
* @return the newly created address attribute.
*/
public static XorRelayedAddressAttribute createXorRelayedAddressAttribute(
TransportAddress address, byte[] tranID) {
XorRelayedAddressAttribute attribute = new XorRelayedAddressAttribute();
// TODO shouldn't we be XORing the address before setting it?
attribute.setAddress(address, tranID);
return attribute;
}
/**
* Creates a XorPeerAddressAttribute of the specified type and with the
* specified address and port
*
* @param address
* the address value of the address attribute
* @param tranID
* the ID of the transaction that we will be using for the XOR
* mask.
* @return the newly created address attribute.
*/
public static XorPeerAddressAttribute createXorPeerAddressAttribute(
TransportAddress address, byte[] tranID) {
XorPeerAddressAttribute attribute = new XorPeerAddressAttribute();
// TODO shouldn't we be XORing the address before setting it?
attribute.setAddress(address, tranID);
return attribute;
}
/**
* Creates a XorMappedAddressAttribute for the specified <tt>address</tt>.
*
* @param address
* the address value of the address attribute
* @param tranID
* the ID of the transaction that we will be using for the XOR
* mask.
*
* @return the newly created XOR address attribute.
*/
public static XorMappedAddressAttribute createXorMappedAddressAttribute(
TransportAddress address, byte[] tranID) {
XorMappedAddressAttribute attribute = new XorMappedAddressAttribute();
attribute.setAddress(address, tranID);
return attribute;
}
/**
* Create a UsernameAttribute.
*
* @param username
* username value
*
* @return newly created UsernameAttribute
*/
public static UsernameAttribute createUsernameAttribute(byte username[]) {
UsernameAttribute attribute = new UsernameAttribute();
attribute.setUsername(username);
return attribute;
}
/**
* Creates a new <tt>UsernameAttribute</tt> instance.
*
* @param username
* the String value of the username
* @return a new <tt>UsernameAttribute</tt> instance
*/
public static UsernameAttribute createUsernameAttribute(String username) {
UsernameAttribute attribute = new UsernameAttribute();
try {
attribute.setUsername(username.getBytes("UTF-8"));
} catch (UnsupportedEncodingException ueex) {
throw new UndeclaredThrowableException(ueex);
}
return attribute;
}
/**
* Creates an empty <tt>MessageIntegrityAttribute</tt>. When included in a
* message the stack would set the body of this attribute so that the the
* HMAC-SHA1 (RFC 2104) would correspond to the actual message that's
* transporting the attribute.
*
* @param username
* the username that we should use to obtain an encryption key
* (password) that the {@link StunAttribute#encode()} method
* should use when creating the content of this message.
*
* @return the newly created address attribute.
*/
public static MessageIntegrityAttribute createMessageIntegrityAttribute(String username, byte[] key) {
MessageIntegrityAttribute attribute = new MessageIntegrityAttribute();
attribute.setKey(key);
attribute.setUsername(username);
return attribute;
}
/**
* Creates an empty <tt>FingerprintAttribute</tt> with a 0 check sum. Once
* included in a message, the value of this attribute will be calculated by
* the stack just before sending it.
*
* @return the newly created <tt>FingerprintAttribute</tt>.
*/
public static FingerprintAttribute createFingerprintAttribute() {
FingerprintAttribute attribute = new FingerprintAttribute();
return attribute;
}
/**
* Create a ChannelNumberAttribute.
*
* @param channelNumber
* channel number
* @return newly created ChannelNumberAttribute
*/
public static ChannelNumberAttribute createChannelNumberAttribute(
char channelNumber) {
ChannelNumberAttribute attribute = new ChannelNumberAttribute();
attribute.setChannelNumber(channelNumber);
return attribute;
}
/**
* Create a RealmAttribute.
*
* @param realm
* realm value
* @return newly created RealmAttribute
*/
public static RealmAttribute createRealmAttribute(byte realm[]) {
RealmAttribute attribute = new RealmAttribute();
attribute.setRealm(realm);
return attribute;
}
/**
* Create a NonceAttribute.
*
* @param nonce
* nonce value
* @return newly created NonceAttribute
*/
public static NonceAttribute createNonceAttribute(byte nonce[]) {
NonceAttribute attribute = new NonceAttribute();
attribute.setNonce(nonce);
return attribute;
}
/**
* Create a SoftwareAttribute.
*
* @param software
* software value
* @return newly created SoftwareAttribute
*/
public static SoftwareAttribute createSoftwareAttribute(byte software[]) {
SoftwareAttribute attribute = new SoftwareAttribute();
attribute.setSoftware(software);
return attribute;
}
/**
* Create a EventAttribute.
*
* @param rFlag
* R flag
* @return the newly created EventPortAttribute
*/
public static EvenPortAttribute createEvenPortAttribute(boolean rFlag) {
EvenPortAttribute attribute = new EvenPortAttribute();
attribute.setRFlag(rFlag);
return attribute;
}
/**
* Create a LifetimeAttribute.
*
* @param lifetime
* lifetime value
* @return newly created LifetimeAttribute
*/
public static LifetimeAttribute createLifetimeAttribute(int lifetime) {
LifetimeAttribute attribute = new LifetimeAttribute();
attribute.setLifetime(lifetime);
return attribute;
}
/**
* Create a RequestedTransportAttribute.
*
* @param protocol
* transport protocol requested
* @return newly created RequestedTransportAttribute
*/
public static RequestedTransportAttribute createRequestedTransportAttribute(
byte protocol) {
RequestedTransportAttribute attribute = new RequestedTransportAttribute();
attribute.setRequestedTransport(protocol);
return attribute;
}
/**
* Create a ReservationTokenAttribute.
*
* @param token
* the token
* @return newly created RequestedTransportAttribute
*/
public static ReservationTokenAttribute createReservationTokenAttribute(
byte token[]) {
ReservationTokenAttribute attribute = new ReservationTokenAttribute();
attribute.setReservationToken(token);
return attribute;
}
/**
* Create a DataAtttribute.
*
* @param data
* the data
* @return newly created DataAttribute
*/
public static DataAttribute createDataAttribute(byte data[]) {
DataAttribute attribute = new DataAttribute();
attribute.setData(data);
return attribute;
}
/**
* Create a DataAtttribute.
*
* @param data
* the data
* @return newly created DataAttribute
*/
public static DataAttribute createDataAttributeWithoutPadding(byte data[]) {
DataAttribute attribute = new DataAttribute(false);
attribute.setData(data);
return attribute;
}
/**
* Creates an Controlled Attribute object with the specified tie-breaker
* value
*
* @param tieBreaker
* the tie-breaker value to be used
* @return the created IceControlledAttribute
*/
public static ControlledAttribute createIceControlledAttribute(
long tieBreaker) {
ControlledAttribute attribute = new ControlledAttribute();
attribute.setTieBreaker(tieBreaker);
return attribute;
}
/**
* Creates a Priority attribute with the specified priority value
*
* @param priority
* the priority value
* @return the created PriorityAttribute
* @throws IllegalArgumentException
* if priority < 0 or priority > (2^31 - 1)
*/
public static PriorityAttribute createPriorityAttribute(long priority)
throws IllegalArgumentException {
PriorityAttribute attribute = new PriorityAttribute();
attribute.setPriority(priority);
return attribute;
}
/**
* Creates a UseCandidateAttribute
*
* @return the created UseCandidateAttribute
*/
public static UseCandidateAttribute createUseCandidateAttribute() {
UseCandidateAttribute attribute = new UseCandidateAttribute();
return attribute;
}
/**
* Creates an Controlling Attribute with the specified tie-breaker value
*
* @param tieBreaker
* the tie-breaker value to be used
*
* @return the created IceControllingAttribute
*/
public static ControllingAttribute createIceControllingAttribute(
long tieBreaker) {
ControllingAttribute attribute = new ControllingAttribute();
attribute.setTieBreaker(tieBreaker);
return attribute;
}
/**
* Creates a MagicCookieAttribute.
*
* @return the created MagicCookieAttribute
*/
public static MagicCookieAttribute createMagicCookieAttribute() {
MagicCookieAttribute attribute = new MagicCookieAttribute();
return attribute;
}
/**
* Creates a DestinationFromAddressAttribute of the specified type and with
* the specified address and port
*
* @param address
* the address value of the address attribute
* @return the newly created address attribute.
*/
public static DestinationAddressAttribute createDestinationAddressAttribute(
TransportAddress address) {
DestinationAddressAttribute attribute = new DestinationAddressAttribute();
attribute.setAddress(address);
return attribute;
}
}