package iax.protocol.frame; import iax.protocol.util.ByteBuffer; public abstract class FullFrame extends Frame { /** * Full frame attribute FrameType: DTMF */ public static final int DTMF_FT = 1; /** * Full frame attribute FrameType: VOICE */ public static final int VOICE_FT = 2; /** * Full frame attribute FrameType: CONTROL */ public static final int CONTROL_FT = 4; /** * Full frame attribute FrameType: IAXPROTOCOLCONTROL */ public static final int PROTOCOLCONTROL_FT = 6; /** * FullFrame's header size in bytes */ protected static final int FULLFRAME_HEADER_LENGTH = FRAME_HEADER_LENGTH + 10; /** * Mask of the bit 0 of a short, for getting the attribute R */ private final int R_SHORTMASK = 0x8000; /** * Mask of the bits 1 to 15 of a short, for getting the attribute DestCallNo */ private final int DESTCALLNO_SHORTMASK = 0x7fff; /** * Mask of the bit 0 of a short, for getting the attribute C */ private final int C_BYTEMASK = 0x80; /** * Mask of the bits 1 to 7 of a short, for getting the attribute SubClass */ private final int SUBCLASS_BYTEMASK = 0x7f; private int retryCount; /** * Flag for the attribute R that says if is a retry frame or not */ protected boolean retry; /** * FullFrame's destination call number attribute */ protected int destCallNo; /** * FullFrame's timestamp attribute */ protected long timestamp; /** * FullFrame's outbound sequence number attribute */ protected int oSeqNo; /** * FullFrame's inbound sequence number attribute */ protected int iSeqNo; /** * FullFrame's frame type attribute */ protected int frameType; /** * Flag for the attribute C that says if the subclass attribute is a power of 2 or not */ protected boolean subclassPowerFormat; /** * FullFrame's subclass attribute */ protected int subclass; /** * Constructor */ protected FullFrame() { super(); } /** * Constructor * @param type frame's type for doing the cast * @param srcCallNo Source call number. * @param retry Indicates if the frame is being retransmitted. * @param destCallNo Destination call number. * @param timeStamp Timestamp of the frame. * @param oSeqno Outbound sequence number. * @param iSeqno Inbound sequence number. * @param frameType frame type attribute * @param subclassPowerFormat flag for the attribute C that says if the subclass attribute is a power of 2 or not * @param subclass subclass * @param data data attached to the frame. */ protected FullFrame (int type, int srcCallNo, boolean retry, int destCallNo, long timeStamp, int oSeqno, int iSeqno, int frameType, boolean subclassPowerFormat, int subclass) { super(type,true,srcCallNo); this.retry = retry; this.destCallNo = destCallNo; this.timestamp = timeStamp; this.oSeqNo = oSeqno; this.iSeqNo = iSeqno; this.frameType = frameType; this.subclassPowerFormat = subclassPowerFormat; this.subclass = subclass; this.retryCount = 0; } /** * Constructor. * @param type frame's type for doing the cast * @param buffer bytes representing the control frame * @throws FrameException when there is a problem with the construction */ protected FullFrame (int type, byte buffer[]) throws FrameException { super(type, buffer); try { byte[] aux = new byte[buffer.length - FRAME_HEADER_LENGTH]; System.arraycopy(buffer, FRAME_HEADER_LENGTH, aux, 0, aux.length); ByteBuffer byteBuffer = new ByteBuffer(aux); int aux8bits; int aux16bits; aux16bits = byteBuffer.get16bits(); retry = (((aux16bits & R_SHORTMASK)==0)?false:true); destCallNo = (aux16bits & DESTCALLNO_SHORTMASK); timestamp = byteBuffer.get32bits(); oSeqNo = byteBuffer.get8bits(); iSeqNo = byteBuffer.get8bits(); frameType = byteBuffer.get8bits(); aux8bits = byteBuffer.get8bits(); subclassPowerFormat = (((aux8bits & C_BYTEMASK)==0)?false:true); subclass = (aux8bits & SUBCLASS_BYTEMASK); /* DESACTIVATED Power Format */ /*if (subclassPowerFormat) //The value of the subclass attribute is a power of 2 subclass = 1 << (aux8bits & SUBCLASS_BYTEMASK); else subclass = (aux8bits & SUBCLASS_BYTEMASK); */ retryCount = 0; } catch (Exception e) { throw new FrameException(e); } } /** * Gets the R attribute * @return true if is a retry, false if not */ public boolean getRetry() { return retry; } /** * Gets the destination call number attribute * @return the destination call number */ public int getDestCallNo() { return destCallNo; } /** * Gets the timestamp attribute * @return the timestamp */ public long getTimestamp() { return timestamp; } /** * Gets the outbound sequence number attribute * @return the outbound sequence number */ public int getOseqno() { return oSeqNo; } /** * Gets de inbound sequence number attribute * @return the inbound sequence number */ public int getIseqno() { return iSeqNo; } /** * Gets the frame type attribute * @return the frame type */ public int getFrameType() { return frameType; } /** * Gets the C attribute * @return true if the subclass is a power of 2, false if not */ public boolean getSubclassPowerFormat() { return subclassPowerFormat; } /** * Gets the subclass attribute * @return the subclass attribute */ public int getSubclass() { return subclass; } /** * Gets the retry count * @return the retry count */ public int getRetryCount() { return retryCount; } /** * Increases the retry count */ public void incRetryCount() { this.retryCount++; } public byte[] serialize() throws FrameException { try { // First is the serialization of the super (the frame's common heather) byte[] superInBytes = super.serialize(); // The result is the super's result and the data attached in the control frame // (FULLFRAME_HEATHER LENGTH is the total, included the FRAME_HEATHER_LENGTH) byte[] thisInBytes = new byte[FULLFRAME_HEADER_LENGTH]; ByteBuffer byteBuffer = new ByteBuffer(FULLFRAME_HEADER_LENGTH-FRAME_HEADER_LENGTH); int aux8bits; int aux16bits; aux16bits = ((retry?R_SHORTMASK:0) + (destCallNo & DESTCALLNO_SHORTMASK)); byteBuffer.put16bits(aux16bits); byteBuffer.put32bits(timestamp); byteBuffer.put8bits(oSeqNo); byteBuffer.put8bits(iSeqNo); byteBuffer.put8bits(frameType); aux8bits = ((subclassPowerFormat?1:0) + (subclass & SUBCLASS_BYTEMASK)); byteBuffer.put8bits(aux8bits); System.arraycopy(superInBytes, 0, thisInBytes, 0, superInBytes.length); System.arraycopy(byteBuffer.getBuffer(), 0, thisInBytes, superInBytes.length, byteBuffer.getBuffer().length); return thisInBytes; } catch (Exception e) { throw new FrameException(e); } } }