package org.freertr.pack; import org.freertr.enc.encTlv; import org.freertr.pipe.pipeSide; import org.freertr.util.bits; import org.freertr.util.logger; /** * inter asterisk exchange (rfc5456) packet * * @author matecsaba */ public class packIax { /** * port number */ public final static int port = 4569; /** * dtmf digit, subclass is the digit */ public final static int typ_dtm = 1; /** * voice data */ public final static int typ_voc = 2; /** * video frame */ public final static int typ_vid = 3; /** * control frame */ public final static int typ_ctr = 4; /** * empty frame */ public final static int typ_nul = 5; /** * iax frame */ public final static int typ_iax = 6; /** * text message */ public final static int typ_txt = 7; /** * image frame */ public final static int typ_img = 8; /** * html frame */ public final static int typ_htm = 9; /** * comfort noise frame, subclass is level */ public final static int typ_cng = 10; /** * other end has hungup */ public final static int ctr_hng = 1; /** * local ring */ public final static int ctr_rng = 2; /** * remote end is ringing */ public final static int ctr_rig = 3; /** * remote end has answered */ public final static int ctr_ans = 4; /** * remote end is busy */ public final static int ctr_bsy = 5; /** * make it go off hook */ public final static int ctr_hok = 6; /** * line is off hook */ public final static int ctr_off = 7; /** * congestion */ public final static int ctr_cng = 8; /** * flash hook */ public final static int ctr_fls = 9; /** * wink */ public final static int ctr_wnk = 10; /** * set an option */ public final static int ctr_opt = 11; /** * key radio */ public final static int ctr_key = 12; /** * unkey radio */ public final static int ctr_uky = 13; /** * call progress */ public final static int ctr_prg = 14; /** * call proceed */ public final static int ctr_prc = 15; /** * call hold */ public final static int ctr_hld = 16; /** * call unhold */ public final static int ctr_uhd = 17; /** * new call */ public final static int iam_new = 1; /** * ping */ public final static int iam_pin = 2; /** * pong */ public final static int iam_pon = 3; /** * ack */ public final static int iam_ack = 4; /** * hangup */ public final static int iam_hup = 5; /** * reject */ public final static int iam_rej = 6; /** * accept */ public final static int iam_acc = 7; /** * authentication request */ public final static int iam_arq = 8; /** * authentication reply */ public final static int iam_arp = 9; /** * invalid message */ public final static int iam_inv = 10; /** * lag request */ public final static int iam_lrq = 11; /** * lag reply */ public final static int iam_lrp = 12; /** * registration request */ public final static int iam_rrq = 13; /** * registration authentication required */ public final static int iam_rau = 14; /** * registration accepted */ public final static int iam_rak = 15; /** * registration rejected */ public final static int iam_rrj = 16; /** * registration release */ public final static int iam_rrl = 17; /** * voice before valid first full frame */ public final static int iam_vnk = 18; /** * dialplan request */ public final static int iam_drq = 19; /** * dialplan reply */ public final static int iam_drp = 20; /** * dial on channel */ public final static int iam_dia = 21; /** * transfer request */ public final static int iam_trq = 22; /** * transfer connect */ public final static int iam_tcn = 23; /** * transfer accepted */ public final static int iam_tac = 24; /** * transfer ready */ public final static int iam_try = 25; /** * transfer release */ public final static int iam_trl = 26; /** * transfer reject */ public final static int iam_trj = 27; /** * stop transmission */ public final static int iam_que = 28; /** * resume transmission */ public final static int iam_uqu = 29; /** * ping but does not require an open connection */ public final static int iam_pok = 30; /** * paging description */ public final static int iam_pag = 31; /** * message waiting indicator */ public final static int iam_mwi = 32; /** * unsupported message received */ public final static int iam_uns = 33; /** * request remote transfer */ public final static int iam_rtq = 34; /** * provision device */ public final static int iam_prv = 35; /** * firmware download */ public final static int iam_fdl = 36; /** * firmware data */ public final static int iam_fdt = 37; /** * called number - string */ public final static int iet_cld = 1; /** * calling number - string */ public final static int iet_cli = 2; /** * calling number ani for billing - string */ public final static int iet_ani = 3; /** * name of caller - string */ public final static int iet_nam = 4; /** * context for number - string */ public final static int iet_ctx = 5; /** * username - string */ public final static int iet_usr = 6; /** * password - string */ public final static int iet_pwd = 7; /** * codec capability - unsigned int */ public final static int iet_cap = 8; /** * desired codec format - unsigned int */ public final static int iet_dsr = 9; /** * desired language - string */ public final static int iet_lng = 10; /** * protocol version - short */ public final static int iet_ver = 11; /** * adsi capability - short */ public final static int iet_ads = 12; /** * originally dialed dnid - string */ public final static int iet_dni = 13; /** * authentication method(s) - short */ public final static int iet_aut = 14; /** * challenge data - string */ public final static int iet_chl = 15; /** * md5 challenge result - string */ public final static int iet_md5 = 16; /** * RSA challenge result - string */ public final static int iet_rsa = 17; /** * apparent address of peer - struct sockaddr_in */ public final static int iet_apr = 18; /** * when to refresh registration - short */ public final static int iet_frs = 19; /** * dialplan status - short */ public final static int iet_dps = 20; /** * call number of peer - short */ public final static int iet_cln = 21; /** * cause - string */ public final static int iet_cse = 22; /** * unknown command - byte */ public final static int iet_unk = 23; /** * how many messages waiting - short */ public final static int iet_msc = 24; /** * request auto-answering -- none */ public final static int iet_aan = 25; /** * request music on hold with quelch -- none or string */ public final static int iet_moh = 26; /** * transfer request identifier -- int */ public final static int iet_tri = 27; /** * referring dnis -- string */ public final static int iet_rdn = 28; /** * provisioning info */ public final static int iet_prv = 29; /** * aes Provisioning info */ public final static int iet_aes = 30; /** * date time */ public final static int iet_dat = 31; /** * device type -- string */ public final static int iet_dev = 32; /** * service identifier -- string */ public final static int iet_svc = 33; /** * firmware revision -- u16 */ public final static int iet_fwr = 34; /** * firmware block description -- u32 */ public final static int iet_fwb = 35; /** * firmware block of data -- raw */ public final static int iet_fwd = 36; /** * provisioning version (u32) */ public final static int iet_pvr = 37; /** * calling presentation (u8) */ public final static int iet_cpr = 38; /** * calling type of number (u8) */ public final static int iet_ctn = 39; /** * calling transit network select (u16) */ public final static int iet_ctr = 40; /** * supported sampling rates (u16) */ public final static int iet_smp = 41; /** * hangup cause (u8) */ public final static int iet_hcs = 42; /** * encryption format (u16) */ public final static int iet_efr = 43; /** * encryption key (raw) */ public final static int iet_eky = 44; /** * codec negotiation */ public final static int iet_fpr = 45; /** * received jitter - u32 */ public final static int iet_jit = 46; /** * received loss - high byte loss pct, low 24 bits loss count */ public final static int iet_lss = 47; /** * total received frames - u32 */ public final static int iet_tot = 48; /** * max playout delay for received frames - u16 */ public final static int iet_del = 49; /** * dropped frames - u32 */ public final static int iet_drp = 50; /** * frames received out of order u32 */ public final static int iet_ood = 51; /** * call number security token */ public final static int iet_tok = 52; private final pipeSide pipe; /** * source call id */ public int sid; /** * target call id */ public int tid; /** * time stamp */ public int times; /** * out sequence */ public int seqO; /** * in sequence */ public int seqI; /** * type */ public int typ; /** * subtype */ public int sub; /** * username */ public String user; /** * refresh */ public int frsh; /** * protocol */ public int proto; /** * desired codec */ public int codecD; /** * capable codec */ public int codecC; /** * calling number */ public String calling; /** * called number */ public String called; /** * original number */ public String origin; /** * create packet handler * * @param lower lower layer to use */ public packIax(pipeSide lower) { pipe = lower; clear(); } /** * clear packet data */ public void clear() { sid = 0; tid = -1; times = 0; seqO = 0; seqI = 0; typ = 0; sub = 0; } /** * bytes ready to receive * * @return bytes */ public int ready2rx() { return pipe.ready2rx(); } /** * check if closed * * @return status */ public int isClosed() { return pipe.isClosed(); } /** * receive one packet * * @param pck buffer to use * @return bytes received */ public int recvPack(packHolder pck) { clear(); pck.clear(); int i = pck.pipeRecv(pipe, 0, -1, 143); if (i < 1) { return i; } i = pck.msbGetW(0); // f src sid = i & 0x7fff; if ((i & 0x8000) == 0) { // mini times = pck.msbGetW(2); // timestamp pck.getSkip(4); typ = typ_voc; return pck.dataSize(); } i = pck.msbGetW(2); // r trg tid = i & 0x7fff; times = pck.msbGetD(4); // timestamp seqO = pck.getByte(8); // out seq seqI = pck.getByte(9); // in seq typ = pck.getByte(10); // type sub = pck.getByte(11); // subtype pck.getSkip(12); return pck.dataSize(); } /** * send one packet * * @param pck buffer to use */ public void sendPack(packHolder pck) { if (tid < 0) { pck.msbPutW(0, sid); // f src pck.msbPutW(2, times); // timestamp pck.putSkip(4); pck.merge2beg(); pck.pipeSend(pipe, 0, pck.dataSize(), 2); return; } pck.msbPutW(0, sid | 0x8000); // f src pck.msbPutW(2, tid); // r trg pck.msbPutD(4, times); // timestamp pck.putByte(8, seqO); // out seq pck.putByte(9, seqI); // in seq pck.putByte(10, typ); // type pck.putByte(11, sub); // subtype pck.putSkip(12); pck.merge2beg(); pck.pipeSend(pipe, 0, pck.dataSize(), 2); } private static encTlv getTlv() { return new encTlv(0, 8, 8, 8, 1, 0, 2, 1, 0, 512, true); } /** * parse tlv * * @param pck buffer to use */ public void parseTlvs(packHolder pck) { switch (typ) { case packIax.typ_iax: case packIax.typ_ctr: break; default: return; } user = null; frsh = 0; proto = 0; codecC = 0; codecD = 0; calling = null; called = null; origin = null; encTlv tlv = getTlv(); for (;;) { if (tlv.getBytes(pck)) { break; } switch (tlv.valTyp) { case iet_usr: user = tlv.getStr(); break; case iet_frs: frsh = bits.msbGetW(tlv.valDat, 0); break; case iet_cld: called = tlv.getStr(); break; case iet_dni: origin = tlv.getStr(); break; case iet_cli: calling = tlv.getStr(); break; case iet_ver: proto = bits.msbGetW(tlv.valDat, 0); break; case iet_cap: codecC = bits.msbGetD(tlv.valDat, 0); break; case iet_dsr: codecD = bits.msbGetD(tlv.valDat, 0); break; } } } /** * parse tlv * * @param pck buffer to use */ public void placeTlvs(packHolder pck) { switch (typ) { case packIax.typ_iax: case packIax.typ_ctr: break; default: return; } encTlv tlv = getTlv(); if (user != null) { tlv.putBytes(pck, iet_usr, user.getBytes()); } if (proto > 0) { bits.msbPutW(tlv.valDat, 0, proto); tlv.putBytes(pck, iet_frs, 2, tlv.valDat); } if (frsh > 0) { bits.msbPutW(tlv.valDat, 0, frsh); tlv.putBytes(pck, iet_frs, 2, tlv.valDat); } if (codecC > 0) { bits.msbPutD(tlv.valDat, 0, codecC); tlv.putBytes(pck, iet_cap, 4, tlv.valDat); } if (codecD > 0) { bits.msbPutD(tlv.valDat, 0, codecD); tlv.putBytes(pck, iet_dsr, 4, tlv.valDat); } if (called != null) { tlv.putBytes(pck, iet_cld, called.getBytes()); } if (calling != null) { tlv.putBytes(pck, iet_cli, calling.getBytes()); } if (origin != null) { tlv.putBytes(pck, iet_dni, origin.getBytes()); } pck.merge2end(); } /** * dump the message * * @param dir direction */ public void dump(String dir) { String tp; String sb = null; switch (typ) { case typ_dtm: tp = "dtmf"; break; case typ_voc: tp = "voice"; break; case typ_vid: tp = "video"; break; case typ_ctr: tp = "control"; switch (sub) { case ctr_hng: sb = "hangup"; break; case ctr_rng: sb = "locRing"; break; case ctr_rig: sb = "remRing"; break; case ctr_ans: sb = "answer"; break; case ctr_bsy: sb = "busy"; break; case ctr_hok: sb = "makeHook"; break; case ctr_off: sb = "lineHook"; break; case ctr_cng: sb = "congestion"; break; case ctr_fls: sb = "flashHook"; break; case ctr_wnk: sb = "wink"; break; case ctr_opt: sb = "option"; break; case ctr_key: sb = "key"; break; case ctr_uky: sb = "unkey"; break; case ctr_prg: sb = "progress"; break; case ctr_prc: sb = "proceed"; break; case ctr_hld: sb = "hold"; break; case ctr_uhd: sb = "unhold"; break; default: sb = "unknown=" + sub; break; } break; case typ_nul: tp = "empty"; break; case typ_iax: tp = "iax"; switch (sub) { case iam_new: sb = "new"; break; case iam_pin: sb = "ping"; break; case iam_pon: sb = "pong"; break; case iam_ack: sb = "ack"; break; case iam_hup: sb = "hangup"; break; case iam_rej: sb = "reject"; break; case iam_acc: sb = "accept"; break; case iam_arq: sb = "authReq"; break; case iam_arp: sb = "authRep"; break; case iam_inv: sb = "inval"; break; case iam_lrq: sb = "lagReq"; break; case iam_lrp: sb = "lagRep"; break; case iam_rrq: sb = "regReq"; break; case iam_rau: sb = "regAuth"; break; case iam_rak: sb = "regAcc"; break; case iam_rrj: sb = "regRej"; break; case iam_rrl: sb = "regRel"; break; case iam_vnk: sb = "vnak"; break; case iam_drq: sb = "planReq"; break; case iam_drp: sb = "planRep"; break; case iam_dia: sb = "dial"; break; case iam_trq: sb = "transReq"; break; case iam_tcn: sb = "transCon"; break; case iam_tac: sb = "transAcc"; break; case iam_try: sb = "transRdy"; break; case iam_trl: sb = "transRel"; break; case iam_trj: sb = "transRej"; break; case iam_que: sb = "pause"; break; case iam_uqu: sb = "resume"; break; case iam_pok: sb = "poke"; break; case iam_pag: sb = "paging"; break; case iam_mwi: sb = "waiting"; break; case iam_uns: sb = "unsupp"; break; case iam_rtq: sb = "transRem"; break; case iam_prv: sb = "provis"; break; case iam_fdl: sb = "firmDl"; break; case iam_fdt: sb = "firmDat"; break; default: sb = "unknown=" + sub; break; } break; case typ_txt: tp = "text"; break; case typ_img: tp = "image"; break; case typ_htm: tp = "html"; break; case typ_cng: tp = "noise"; break; default: tp = "unknown=" + typ; break; } if (sb == null) { sb = "" + sub; } logger.debug(dir + ": typ=" + tp + " sub=" + sb + " sid=" + sid + " tid=" + tid + " seqi=" + seqI + " seqo=" + seqO); } }