package com.cari.voip.keyboard.stack.events;
import java.io.IOException;
import java.io.Reader;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.cari.voip.keyboard.stack.parsers.PacketParseException;
import com.cari.voip.keyboard.stack.parsers.PacketParser;
public class Packet {
public static final int TYPE_INVALIDE = 0;
public static final int TYPE_AUTH_REQUEST = 1;
public static final int TYPE_AUTH = TYPE_AUTH_REQUEST+1;
public static final int TYPE_AUTH_REPLY = TYPE_AUTH_REQUEST+2;
public static final int TYPE_TRAP = 5;
public static final int TYPE_TRAP_USER = TYPE_TRAP+1;
public static final int TYPE_TRAP_REG_USER = TYPE_TRAP+2;
public static final int TYPE_TRAP_DISPATCHER = TYPE_TRAP+3;
public static final int TYPE_TRAP_CALL = TYPE_TRAP+4;
public static final int TYPE_TRAP_ALL_USERS = TYPE_TRAP+5;
public static final int TYPE_TRAP_ALL_REG_USERS = TYPE_TRAP+6;
public static final int TYPE_TRAP_ALL_DISPATCHERS = TYPE_TRAP+7;
public static final int TYPE_TRAP_ALL_CURRENT_CALLS = TYPE_TRAP+8;
public static final int TYPE_TRAP_MESSAGE = TYPE_TRAP+9;
public static final int TYPE_TRAP_ALL_GATEWAYS = TYPE_TRAP+10;
public static final int TYPE_TRAP_CALL_DISPATCHER_PROGRESS = TYPE_TRAP+11;
public static final int TYPE_TRAP_CALL_DISPATCHER_HANGUP = TYPE_TRAP+12;
public static final int TYPE_TRAP_CALL_DISPATCHER_FAIL = TYPE_TRAP+13;
public static final int TYPE_TRAP_CALL_DISPATCHER_ANSWER = TYPE_TRAP+14;
public static final int TYPE_TRAP_CFG_DISPAT_CALL = TYPE_TRAP+15;
public static final int TYPE_TRAP_END = TYPE_TRAP+16;
public static final int TYPE_REPLY = 30;
public static final int TYPE_REPLY_DISPAT = TYPE_REPLY+1;
public static final int TYPE_REPLY_QUERY_ALL_USERS = TYPE_REPLY+2;
public static final int TYPE_REPLY_QUERY_ALL_REG_USERS = TYPE_REPLY+3;
public static final int TYPE_REPLY_QUERY_ALL_DISPATCHERS = TYPE_REPLY+4;
public static final int TYPE_REPLY_QUERY_ALL_CURRENT_CALLS = TYPE_REPLY+5;
public static final int TYPE_REPLY_MESSAGE = TYPE_REPLY+6;
public static final int TYPE_REPLY_QUERY_ALL_GATEWAYS = TYPE_REPLY+7;
public static final int TYPE_REPLY_M_REGISTER = TYPE_REPLY+8;
public static final int TYPE_REPLY_API = TYPE_REPLY+9;
public static final int TYPE_REPLY_ERROR = TYPE_REPLY+10;
public static final int TYPE_REPLY_END = TYPE_REPLY+11;
public static final int TYPE_COMMAND = 50;
public static final int TYPE_COMMAND_DISPAT = TYPE_COMMAND + 1;
public static final int TYPE_COMMAND_QUERY_ALL_USERS = TYPE_COMMAND + 2;
public static final int TYPE_COMMAND_QUERY_ALL_REG_USERS = TYPE_COMMAND + 3;
public static final int TYPE_COMMAND_QUERY_ALL_DISPATCHERS = TYPE_COMMAND + 4;
public static final int TYPE_COMMAND_QUERY_ALL_CURRENT_CALLS = TYPE_COMMAND + 5;
public static final int TYPE_COMMAND_MESSAGE = TYPE_COMMAND + 6;
public static final int TYPE_COMMAND_QUERY_ALL_GATEWAYS = TYPE_COMMAND + 7;
public static final int TYPE_COMMAND_M_REGISTER = TYPE_COMMAND + 8;
public static final int TYPE_COMMAND_API = TYPE_COMMAND + 9;
public static final int TYPE_COMMAND_END = TYPE_COMMAND + 10;
public static final String[] TYPES={
"invalid-packet-type",
"auth/request",
"auth",
"auth/reply",
"",
"",
"trap/user",
"trap/registratioin",
"trap/dispatcher",
"trap/call",
"trap/all-users",
"trap/all-reg-users",
"trap/all-dispatchers",
"trap/all-current-calls",
"trap/message",
"trap/all-gateways",
"trap/call-dispatcher-progress",
"trap/call-dispatcher-hangup",
"trap/call-dispatcher-fail",
"trap/call-dispatcher-answer",
"trap/cfg-dispat-call",
"trap/call-dispatcher-wait",
"trap/call-dispatcher-hold",
"",
"",
"",
"",
"",
"",
"",
"",
"reply/dispatch",
"reply/query-all-users",
"reply/query-all-reg-users",
"reply/query-all-dispatchers",
"reply/query-all-current-calls",
"reply/message",
"reply/query-all-gateways",
"reply/m-register",//ok,err
"reply/api",
"reply/error",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"command/dispatch",
"command/query-all-users",
"command/query-all-reg-users",
"command/query-all-dispatchers",
"command/query-all-current-calls",
"command/message",
"command/query-all-gateways",
"command/m-register",//mcode rcode
"command/api",
""
};
public static final String PACKET_START_TOKEN = "content-type";
public static final String ERR_DISCRIPTION = "discription";
public static final String BODY_LENGTH = "content-length";
public static Map<String,Integer> typeMap = null;
public static Map<Integer,PacketDescription> descriptionMap = null;
public static int getPacketTypeFromString(String typeString){
int typeInt = TYPE_INVALIDE;
if(typeMap == null){
typeMap = new HashMap<String,Integer>();
try{
for(int i = 0; i< TYPES.length;i++){
if(TYPES[i] != null &&
TYPES[i].length() != 0){
typeMap.put(TYPES[i], new Integer(i));
}
}
}
catch(Exception e){
}
}
if(typeString != null && typeString.length() > 0){
Integer typeInteger = (Integer)(typeMap.get(typeString));
if(typeInteger != null){
typeInt = typeInteger.intValue();
}
}
//System.out.print("\t"+typeString+":"+String.valueOf(typeInt)+"\n");
return typeInt;
}
public static int getPacketTypeFromLine(String line){
int typeInt = -1;
int k = -1;
int len = 0;
if(line != null && (len =line.length()) > 0){
String lowerCaseLine = line.toLowerCase();
if((k = lowerCaseLine.indexOf(PACKET_START_TOKEN)) >= 0){
int state = 0;
k += PACKET_START_TOKEN.length();
int typeStartIndex= k;
while(k < len){
char c = line.charAt(k);
switch(state){
case 0://null
if(Character.isLetter(c)){
typeStartIndex = k;
state = 1;
}
break;
case 1://xxx
if(Character.isSpaceChar(c)){
String typeString = line.substring(typeStartIndex, k);
typeInt = getPacketTypeFromString(typeString);
state = 3;
}
break;
default:
break;
}
if(state == 3){
break;
}
k++;
}
if(typeInt == -1){
String typeString = line.substring(typeStartIndex);
typeInt = getPacketTypeFromString(typeString);
}
}
}
if(typeInt == -1){
typeInt = TYPE_INVALIDE;
}
return typeInt;
}
public static final String AUTH_REQUEST = "auth/request";
public static final String AUTH_RESPONSE = "auth";
public static final String AUTH_REPLY = "auth/reply";
public static final String COMMAND = "command";
public static final String REPLY = "reply";
public static final String TRAP = "trap";
public static final String PROP_REPLY_TEXT="reply-text";
public static final String PROP_ERR_DISPCRIPTION="discription";
public static final String PROP_CONNECTION_ID="connection-id";
public static final String PROP_DISPATCHER="dispatcher";
public static final String PROP_PASSWORD="password";
public static final String PROP_REPLY_OK="ok";
public static final String PROP_REPLY_ERROR = "err";
private int packetType;
private String head = null;
private String body = null;
private XMLBody xmlBody= null;
private ReplyListener replyListener;
public Packet(){
}
public Packet(int type){
if(type >=0 && type< TYPES.length){
this.packetType = type;
}
}
public int getPacketType(){
return this.packetType;
}
public boolean isTrap(){
return (this.packetType> TYPE_TRAP)&& (this.packetType < TYPE_TRAP_END);
}
public boolean isReply(){
return (this.packetType> TYPE_REPLY)&& (this.packetType < TYPE_REPLY_END);
}
public boolean isCommand(){
return (this.packetType> TYPE_COMMAND)&& (this.packetType < TYPE_COMMAND_END);
}
public void setHead(String head){
this.head = head;
}
public String getHead(){
return this.head;
}
public void setBody(String body) throws XMLParseException{
if(body == null || body.length() == 0){
return;
}
this.body = body;
//System.out.print(body.length()+"\n"+body);
if(this.xmlBody == null){
this.xmlBody = new XMLBody();
}
this.xmlBody.parseStr(this.body);
}
public String getBody(){
return this.body;
}
public XMLBody getXMLBody(){
return this.xmlBody;
}
public void setPacketFromParser(PacketParser parser) throws PacketParseException{
boolean ok = true;
Reader reader = null;
if(parser == null ||
(reader = parser.getReader()) == null){
throw new PacketParseException("��������մ���reader Ϊ��");
}
String line = parser.readLine();
int k = -1;
StringBuilder hb = new StringBuilder(128);
while(line != null &&
line.length() > 0){
k = -1;
k = line.indexOf(':');
if(k > 0){
String name = line.substring(0, k).trim().toLowerCase();
String value = line.substring(k+1).trim();
this.setProperty(name, value);
}
hb.append(line);
line = parser.readLine();
}
if(line == null){
throw new PacketParseException("��������մ������������ж�");
}
if(hb.length() > 0){
this.setHead(hb.toString());
}
Object bodyLen = this.getProperty(Packet.BODY_LENGTH);
int len =0;
int lenOri = 0;
if(bodyLen != null){
try{
len = Integer.parseInt(bodyLen.toString());
}
catch(NumberFormatException e){
throw new PacketParseException("��������մ�������������");
}
}
if(len > 0){
//System.out.print("\t len:"+String.valueOf(len)+"\n");
StringBuilder bb = new StringBuilder(len);
lenOri = len;
//boolean first = true;
while(len > 0){
try{
int reLen=
reader.read(parser.bodyBuf, 0, 1);//len>parser.bodyBuf.length?parser.bodyBuf.length:len);
if(reLen == -1){
break;//end of stream
}
if(reLen > 0){
String ad = String.valueOf(parser.bodyBuf, 0, reLen);
bb.append(ad);
len -= ad.getBytes("UTF-8").length;
/*if(first && (lenOri-len) != bb.toString().length()){
first = false;
System.out.print(reLen+"=>"+(lenOri-len)+"-"+bb.toString().length()+"\n"+bb.toString());
}*/
}
}
catch(IOException e){
throw new PacketParseException("��������մ�������IO����");
}
}
//if(bb.length() == lenOri){
try{
this.setBody(bb.toString());
}
catch(XMLParseException e){
throw new PacketParseException("�����xml���ݽ�������"+e.getMessage());
}
//}
//else{
// throw new PacketParseException("��������մ��������жϵ��°��ڲ�û��ȫ������");
//}
}
}
private final Map<String,Object> properties = new HashMap<String, Object>();
/**
* Returns the packet property with the specified name or <tt>null</tt> if the
* property doesn't exist. Property values that were orginally primitives will
* be returned as their object equivalent. For example, an int property will be
* returned as an Integer, a double as a Double, etc.
*
* @param name the name of the property.
* @return the property, or <tt>null</tt> if the property doesn't exist.
*/
public synchronized Object getProperty(String name) {
if (properties == null) {
return null;
}
return properties.get(name);
}
/**
* Sets a property with an Object as the value. The value must be Serializable
* or an IllegalArgumentException will be thrown.
*
* @param name the name of the property.
* @param value the value of the property.
*/
public synchronized void setProperty(String name, Object value) {
if (!(value instanceof Serializable)) {
throw new IllegalArgumentException("Value must be serialiazble");
}
properties.put(name, value);
}
public void setReplyHandler(ReplyListener replyHandler){
this.replyListener = replyHandler;
}
public ReplyListener getReplyHandler(){
return this.replyListener;
}
public String toString(){
int type = 0;
if(this.packetType >=0 && this.packetType< TYPES.length){
type = this.packetType;
}
String typeString = TYPES[type];
StringBuilder sb = new StringBuilder(128);
sb.append(PACKET_START_TOKEN+":"+typeString+"\n");
int props = properties.size();
if(props > 0){
for(String key:properties.keySet()){
if(key != null){
String val = (String)properties.get(key);
if(val != null){
sb.append(key+":"+val+"\n");
}
}
}
}
if(this.body != null){
int len;
try {
len = this.body.getBytes("UTF-8").length;
sb.append(Packet.BODY_LENGTH+":"+String.valueOf(len)+"\n");
sb.append("\n");
sb.append(body);
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
//e.printStackTrace();
sb.append("\n");
}
}
else{
sb.append("\n");
}
return sb.toString();
}
protected static void makeDescriptionMap(){
if(descriptionMap != null){
return;
}
descriptionMap = new HashMap<Integer,PacketDescription>();
descriptionMap.put(new Integer(Packet.TYPE_REPLY_DISPAT), new PacketDescription(){
@Override
public String[] getDescription(Packet packet) {
if(packet.getPacketType() == Packet.TYPE_REPLY_DISPAT){
//StringBuilder sb = new StringBuilder();
List<String> re = new ArrayList<String>(3);
re.add("����");
Object replytext = packet.getProperty("reply-text");
if(replytext != null && replytext instanceof String){
String replytextstring = (String)replytext;
if(replytextstring.indexOf("err") >= 0 ){
re.add("���ɹ�");
Object description = packet.getProperty(Packet.ERR_DISCRIPTION);
if(description != null && description instanceof String){
String descriptionString = (String)description;
re.add(descriptionString);
}
}
else{
re.add("�ɹ�");
}
}
return re.toArray(new String[]{});
}
return null;
}});
descriptionMap.put(new Integer(Packet.TYPE_REPLY_MESSAGE), new PacketDescription(){
@Override
public String[] getDescription(Packet packet) {
if(packet.getPacketType() == Packet.TYPE_REPLY_MESSAGE){
//StringBuilder sb = new StringBuilder();
List<String> re = new ArrayList<String>(3);
//sb.append("����");
re.add("����");
Object replytext = packet.getProperty("reply-text");
if(replytext != null && replytext instanceof String){
String replytextstring = (String)replytext;
if(replytextstring.indexOf("err") >= 0 ){
re.add("���ɹ�");
Object description = packet.getProperty(Packet.ERR_DISCRIPTION);
if(description != null && description instanceof String){
String descriptionString = (String)description;
re.add(descriptionString);
}
}
else{
re.add("�ɹ�");
}
}
return re.toArray(new String[]{});
}
return null;
}
}
);
descriptionMap.put(new Integer(Packet.TYPE_TRAP_CALL), new PacketDescription(){
@Override
public String[] getDescription(Packet packet) {
if(packet.getPacketType() == Packet.TYPE_TRAP_CALL){
//StringBuilder sb = new StringBuilder();
List<String> re = new ArrayList<String>(3);
//sb.append("����");
String userId = (String)packet.getProperty("id");
String action = (String)packet.getProperty("action");
String bound = (String)packet.getProperty("bound");
String flag = (String)packet.getProperty("flag");
re.add(userId);
if(action.equals("ring")){
String d = "";
if(bound !=null){
if(bound.indexOf("in") >= 0){
re.add("����");
d += "����";
}
else{
re.add("����");
d += "����";
}}
else{
re.add("����");
}
re.add(d);
}
else if(action.equals("answer")){
re.add("Ӧ��");
String d = "";
if(bound != null){
if(bound.indexOf("in") >= 0){
d += "����";
}
else{
d += "����";
}
}
re.add(d);
}
else if(action.equals("add") || action.equals("flag")){
re.add("��ʼͨ��");
String d = "";
if(bound !=null){
if(bound.indexOf("in") >= 0){
d += "����";
}
else{
d += "����";
}}
if(flag != null){
if(flag.indexOf("speak") >= 0){
d += "(��˵)";
}
else{
d += "(��)";
}}
re.add(d);
}else if(action.equals("del")){
re.add("����ͨ��");
String d = "";
if(bound != null){
if(bound.indexOf("in") >= 0){
d += "����";
}
else{
d += "����";
}
}
re.add(d);
}
else if(action.equals("hangup")){
re.add("�һ�");
String d = "";
if(bound != null){
if(bound.indexOf("in") >= 0){
d += "����";
}
else{
d += "����";
}
}
re.add(d);
}
return re.toArray(new String[]{});
}
return null;
}
}
);
}
public String[] getDiscription(){
if(descriptionMap == null){
makeDescriptionMap();
}
PacketDescription d = descriptionMap.get(new Integer(this.packetType));
if(d != null){
return d.getDescription(Packet.this);
}
return null;
//return new String[]{TYPES[this.packetType]};
}
}