package iax.protocol.util;
import java.util.HashMap;
import org.bouncycastle.crypto.digests.MD5Digest;
import iax.protocol.frame.ControlFrame;
import iax.protocol.frame.Frame;
import iax.protocol.frame.FrameException;
import iax.protocol.frame.FullFrame;
import iax.protocol.frame.MiniFrame;
import iax.protocol.frame.ProtocolControlFrame;
import iax.protocol.frame.VoiceFrame;
/**
* Utiliy class to work with frames.
*/
public class FrameUtil {
//Posicion de F en bytes
private static final int F_POS = 0;
//Posicion de FrameType em bytes
private static final int FRAMETYPE_POS = 10;
//MD5 result size in bytes
private static final int MD5_SIZE = 16;
//Mapping to reply full frames
private static final HashMap replyMap;
static {
replyMap = new HashMap();
int accept[] = {ProtocolControlFrame.AUTHREP_SC, ProtocolControlFrame.NEW_SC};
int authreq[] = {ProtocolControlFrame.NEW_SC};
int pong[] = {ProtocolControlFrame.PING_SC};
int regack[] = {ProtocolControlFrame.REGREQ_SC};
int regauth[] = {ProtocolControlFrame.REGREL_SC, ProtocolControlFrame.REGREQ_SC};
int regrej[] = {ProtocolControlFrame.REGREL_SC, ProtocolControlFrame.REGREQ_SC};
int reject[] = {ProtocolControlFrame.AUTHREP_SC};
replyMap.put(ProtocolControlFrame.ACCEPT_SC, accept);
replyMap.put(ProtocolControlFrame.AUTHREQ_SC, authreq);
replyMap.put(ProtocolControlFrame.PONG_SC, pong);
replyMap.put(ProtocolControlFrame.REGACK_SC, regack);
replyMap.put(ProtocolControlFrame.REGAUTH_SC, regauth);
replyMap.put(ProtocolControlFrame.REGREJ_SC, regrej);
replyMap.put(ProtocolControlFrame.REJECT_SC, reject);
}
/**
* Deserialize a frame from its bytes.
* @param buffer Frame bytes stored in an array.
* @return A new frame of suitable type filled with data.
* @throws FrameException
*/
public static Frame deserialize(byte buffer[]) throws FrameException {
ByteBuffer byteBuffer = new ByteBuffer(buffer);
try {
boolean full = (((byteBuffer.get16bits(F_POS) & Frame.F_SHORTMASK)==0)?false:true);
if (!full) {
return new MiniFrame(buffer);
} else {
int frameType = byteBuffer.get8bits(FRAMETYPE_POS);
switch(frameType) {
case FullFrame.CONTROL_FT:
return new ControlFrame(buffer);
case FullFrame.PROTOCOLCONTROL_FT:
return new ProtocolControlFrame(buffer);
case FullFrame.VOICE_FT:
return new VoiceFrame(buffer);
default:
} throw new FrameException("Frame type unknown");
}
} catch (Exception e) {
throw new FrameException(e);
}
}
/**
* Computes the md5 result
* @param challenge challenge in bytes for the md5
* @param password password in bytes for the md5
* @return
*/
public static byte[] md5(byte[] challenge, byte[] password) {
MD5Digest md = new MD5Digest();
md.update(challenge, 0, challenge.length);
md.update(password, 0, password.length);
byte result[] = new byte[MD5_SIZE];
md.doFinal(result, 0);
return result;
}
/**
* Gets an array with the subclass values replied by the subclass value passed in args
* @param recvSubclass the subclass value for making the reply
* @return an array with the subclass values replied
*/
public static int[] getReplySubclasses(int recvSubclass) {
if (replyMap.containsKey(recvSubclass))
return (int[])replyMap.get(recvSubclass);
else return new int[0];
}
}