public static Message decode(byte binMessage[],char offset,char arrayLen) throws StunException {
  int originalOffset=offset;
  arrayLen=(char)Math.min(binMessage.length,arrayLen);
  if (binMessage == null || arrayLen - offset < Message.HEADER_LENGTH) {
    throw new StunException(StunException.ILLEGAL_ARGUMENT,"The given binary array is not a valid StunMessage");
  }
  char messageType=(char)((binMessage[offset++] << 8) | (binMessage[offset++] & 0xFF));
  Message message;
  if (Message.isResponseType(messageType) && messageType != OLD_DATA_INDICATION)   message=new Response();
 else   if (Message.isRequestType(messageType))   message=new Request();
 else   message=new Indication();
  message.setMessageType(messageType);
  int length=(char)((binMessage[offset++] << 8) | (binMessage[offset++] & 0xFF));
  byte cookie[]=new byte[4];
  System.arraycopy(binMessage,offset,cookie,0,4);
  offset+=4;
  boolean rfc3489Compat=false;
  if (!Arrays.equals(MAGIC_COOKIE,cookie)) {
    rfc3489Compat=true;
  }
  if (arrayLen - offset - TRANSACTION_ID_LENGTH < length) {
    throw new StunException(StunException.ILLEGAL_ARGUMENT,"The given binary array does not seem to contain" + " a whole StunMessage: given " + ((int)arrayLen) + " bytes of "+ message.getName()+ " but expecting "+ (offset + TRANSACTION_ID_LENGTH + length));
  }
  byte tranID[]=new byte[TRANSACTION_ID_LENGTH];
  System.arraycopy(binMessage,offset,tranID,0,TRANSACTION_ID_LENGTH);
  try {
    if (rfc3489Compat) {
      byte rfc3489TranID[]=new byte[TRANSACTION_ID_LENGTH + 4];
      System.arraycopy(cookie,0,rfc3489TranID,0,4);
      System.arraycopy(tranID,0,rfc3489TranID,4,TRANSACTION_ID_LENGTH);
      message.setTransactionID(rfc3489TranID);
    }
 else {
      message.setTransactionID(tranID);
    }
  }
 catch (  StunException exc) {
    throw new StunException(StunException.ILLEGAL_ARGUMENT,"The given binary array does not seem to " + "contain a whole StunMessage",exc);
  }
  offset+=TRANSACTION_ID_LENGTH;
  while (offset - Message.HEADER_LENGTH < length) {
    Attribute att=AttributeDecoder.decode(binMessage,offset,(char)(length - offset));
    performAttributeSpecificActions(att,binMessage,originalOffset,offset);
    message.putAttribute(att);
    offset+=att.getDataLength() + Attribute.HEADER_LENGTH;
    if ((att.getDataLength() % 4) > 0) {
      offset+=(4 - (att.getDataLength() % 4));
    }
  }
  return message;
}

public static Message decode ( byte binMessage [ ] , char offset , char arrayLen ) throws StunException { int originalOffset = offset ; arrayLen = ( char ) Math . min ( binMessage . length , arrayLen ) ; if ( binMessage == null || arrayLen - offset < Message . HEADER_LENGTH ) { throw new StunException ( StunException . ILLEGAL_ARGUMENT , "The given binary array is not a valid StunMessage" ) ; } char messageType = ( char ) ( ( binMessage [ offset ++ ] << 8 ) | ( binMessage [ offset ++ ] & 0xFF ) ) ; Message message ; if ( Message . isResponseType ( messageType ) && messageType != OLD_DATA_INDICATION ) message = new Response ( ) ; else if ( Message . isRequestType ( messageType ) ) message = new Request ( ) ; else message = new Indication ( ) ; message . setMessageType ( messageType ) ; int length = ( char ) ( ( binMessage [ offset ++ ] << 8 ) | ( binMessage [ offset ++ ] & 0xFF ) ) ; byte cookie [ ] = new byte [ 4 ] ; System . arraycopy ( binMessage , offset , cookie , 0 , 4 ) ; offset += 4 ; boolean rfc3489Compat = false ; if ( ! Arrays . equals ( MAGIC_COOKIE , cookie ) ) { rfc3489Compat = true ; } if ( arrayLen - offset - TRANSACTION_ID_LENGTH < length ) { throw new StunException ( StunException . ILLEGAL_ARGUMENT , "The given binary array does not seem to contain" + " a whole StunMessage: given " + ( ( int ) arrayLen ) + " bytes of " + message . getName ( ) + " but expecting " + ( offset + TRANSACTION_ID_LENGTH + length ) ) ; } byte tranID [ ] = new byte [ TRANSACTION_ID_LENGTH ] ; System . arraycopy ( binMessage , offset , tranID , 0 , TRANSACTION_ID_LENGTH ) ; try { if ( rfc3489Compat ) { byte rfc3489TranID [ ] = new byte [ TRANSACTION_ID_LENGTH + 4 ] ; System . arraycopy ( cookie , 0 , rfc3489TranID , 0 , 4 ) ; System . arraycopy ( tranID , 0 , rfc3489TranID , 4 , TRANSACTION_ID_LENGTH ) ; message . setTransactionID ( rfc3489TranID ) ; } else { message . setTransactionID ( tranID ) ; } } catch ( StunException exc ) { throw new StunException ( StunException . ILLEGAL_ARGUMENT , "The given binary array does not seem to " + "contain a whole StunMessage" , exc ) ; } offset += TRANSACTION_ID_LENGTH ; while ( offset - Message . HEADER_LENGTH < length ) { Attribute att = AttributeDecoder . decode ( binMessage , offset , ( char ) ( length - offset ) ) ; performAttributeSpecificActions ( att , binMessage , originalOffset , offset ) ; message . putAttribute ( att ) ; offset += att . getDataLength ( ) + Attribute . HEADER_LENGTH ; if ( ( att . getDataLength ( ) % 4 ) > 0 ) { offset += ( 4 - ( att . getDataLength ( ) % 4 ) ) ; } } return message ; }
constructs a message from its binary representation .
