/*
*
* 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.control;
import org.restcomm.media.stun.StunException;
import org.restcomm.media.stun.messages.attributes.StunAttribute;
public abstract class ControlAttribute extends StunAttribute {
protected static final String ICE_CONTROLLED_NAME = "ICE_CONTROLLED";
protected static final String ICE_CONTROLLING_NAME = "ICE_CONTROLLING";
protected static final char DATA_LENGTH = 8;
protected long tieBreaker;
protected boolean controlling;
protected ControlAttribute(boolean isControlling) {
super(isControlling ? StunAttribute.ICE_CONTROLLING
: StunAttribute.ICE_CONTROLLED);
this.tieBreaker = -1;
this.controlling = isControlling;
}
public long getTieBreaker() {
return tieBreaker;
}
public void setTieBreaker(long tieBreaker) {
this.tieBreaker = tieBreaker;
}
public boolean isControlling() {
return controlling;
}
@Override
protected void decodeAttributeBody(byte[] data, char offset, char length)
throws StunException {
// Reading in the network byte order (Big-Endian)
tieBreaker = ((data[offset++] & 0xffl) << 56)
| ((data[offset++] & 0xffl) << 48)
| ((data[offset++] & 0xffl) << 40)
| ((data[offset++] & 0xffl) << 32)
| ((data[offset++] & 0xffl) << 24)
| ((data[offset++] & 0xffl) << 16)
| ((data[offset++] & 0xffl) << 8) | (data[offset++] & 0xffl);
}
@Override
public char getDataLength() {
return DATA_LENGTH;
}
@Override
public String getName() {
if (this.controlling) {
return ICE_CONTROLLING_NAME;
}
return ICE_CONTROLLED_NAME;
}
@Override
public byte[] encode() {
char type = getAttributeType();
byte[] binValue = new byte[HEADER_LENGTH + getDataLength()];
// Type
binValue[0] = (byte) (type >> 8);
binValue[1] = (byte) (type & 0x00FF);
// Length
binValue[2] = (byte) (getDataLength() >> 8);
binValue[3] = (byte) (getDataLength() & 0x00FF);
// Tie-Breaker
binValue[4] = (byte) ((tieBreaker & 0xFF00000000000000L) >> 56);
binValue[5] = (byte) ((tieBreaker & 0x00FF000000000000L) >> 48);
binValue[6] = (byte) ((tieBreaker & 0x0000FF0000000000L) >> 40);
binValue[7] = (byte) ((tieBreaker & 0x000000FF00000000L) >> 32);
binValue[8] = (byte) ((tieBreaker & 0x00000000FF000000L) >> 24);
binValue[9] = (byte) ((tieBreaker & 0x0000000000FF0000L) >> 16);
binValue[10] = (byte) ((tieBreaker & 0x000000000000FF00L) >> 8);
binValue[11] = (byte) (tieBreaker & 0x00000000000000FFL);
return binValue;
}
@Override
public boolean equals(Object other) {
if (other == null || !(other instanceof ControlAttribute)) {
return false;
}
if (other == this) {
return true;
}
ControlAttribute iceControlAtt = (ControlAttribute) other;
if (iceControlAtt.getAttributeType() != this.getAttributeType()
|| iceControlAtt.controlling != this.controlling
|| iceControlAtt.getDataLength() != DATA_LENGTH
|| iceControlAtt.getTieBreaker() != this.tieBreaker) {
return false;
}
return true;
}
}