/*********************************************************** Copyright (C), LGC Wireless. File Name: isdn_rm.c Description: ISDN Resource Management Version: v9.0.0 Author: Gengxin Chen Create Date: 2008-2-19 History: ************************************************************/ #include "./include/isdn_const.h" #include "../../m2ua/src/include/m2ua_const.h" #include "./include/isdn_rm.h" #include "./include/isdn_debug.h" #include "./include/isdn_ext.h" #include "./include/isdn_inc.h" extern void isdn_cpc_proc(u32 pid); extern void service_bc_proc(u32 pid); extern void service_dc_proc(u32 pid); extern void isdn_restart_ctrl(u32 pid); extern int isdn_rel_proc(u32 pid, u32 cause); extern int rel_cr(u32 pid); extern inline void isdn_cpc_clear(ISDN_Port_struct *pPort); extern int isdn_event_handle(u32 pid, u8 primitive); extern void isdn_set_cause(CauseStr *cause_ptr, u8 val); extern void isdn_set_status(IsdnStatus *status_ptr, u8 state, u8 cause_val); //msc extern int msc_give_cic_value(u32 tg_id, int head_cic); static int isdn_encode_alert(u8 *dst, IsdnMsgStr *src, int variant) { IsdnAlert *ptr = &src->msg_list.alert; u8 *flw_ptr = dst; //Optional if(variant == VARIANT_ITU) { if(ptr->br_cap.pres == 1) { flw_ptr[0] = IE_BR_CAP; flw_ptr[1] = itu_encode_br_cap(flw_ptr+2, &ptr->br_cap); flw_ptr += flw_ptr[1] + 2; } } if(ptr->chnl_id.pres == 1) { flw_ptr[0] = IE_CHNL_ID; if(variant == VARIANT_QSIG) flw_ptr[1] = qsig_encode_chnl_id(flw_ptr+2, &ptr->chnl_id); else flw_ptr[1] = isdn_encode_chnl_id(flw_ptr+2, &ptr->chnl_id); flw_ptr += flw_ptr[1] + 2; } if(ptr->prg_ind.pres == 1) { flw_ptr[0] = IE_PRG_IND; flw_ptr[1] = isdn_encode_prg_ind(flw_ptr+2, &ptr->prg_ind); flw_ptr += flw_ptr[1] + 2; } if(variant == VARIANT_ITU) { if(ptr->disp.pres == 1) { flw_ptr[0] = IE_DISP; flw_ptr[1] = isdn_encode_disp(flw_ptr+2, &ptr->disp); flw_ptr += flw_ptr[1] + 2; } if(ptr->sign.pres == 1) { flw_ptr[0] = IE_SIGN; flw_ptr[1] = isdn_encode_sign(flw_ptr+2, &ptr->sign); flw_ptr += flw_ptr[1] + 2; } if(ptr->hl_comp.pres == 1) { flw_ptr[0] = IE_HL_COMP; flw_ptr[1] = isdn_encode_hl_comp(flw_ptr+2, &ptr->hl_comp); flw_ptr += flw_ptr[1] + 2; } } return flw_ptr - dst; } int isdn_decode_alert(IsdnMsgStr *dst, u8 *src, int variant, u8 len) { IsdnAlert *ptr = &dst->msg_list.alert; u8 *flw_ptr = src; while(flw_ptr+2-src <= len) { if(*flw_ptr == 0) { break; } switch(*flw_ptr) { case IE_BR_CAP: if(variant == VARIANT_ITU) itu_decode_br_cap(&ptr->br_cap, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; case IE_CHNL_ID: if(variant == VARIANT_QSIG) qsig_decode_chnl_id(&ptr->chnl_id, flw_ptr+2, flw_ptr[1]); else isdn_decode_chnl_id(&ptr->chnl_id, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; case IE_PRG_IND: isdn_decode_prg_ind(&ptr->prg_ind, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; case IE_DISP: if(variant == VARIANT_ITU) isdn_decode_disp(&ptr->disp, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; case IE_SIGN: if(variant == VARIANT_ITU) isdn_decode_sign(&ptr->sign, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; case IE_HL_COMP: if(variant == VARIANT_ITU) isdn_decode_hl_comp(&ptr->hl_comp, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; default: if(*flw_ptr >= 0x80) //single octet IE flw_ptr += 1; else flw_ptr += flw_ptr[1] + 2; break; } } return ISDN_CM_OK; } static int isdn_encode_call_proc(u8 *dst, IsdnMsgStr *src, int variant) { IsdnCallProc *ptr = &src->msg_list.callProc; u8 *flw_ptr = dst; //Optional if(variant == VARIANT_ITU) { if(ptr->br_cap.pres == 1) { flw_ptr[0] = IE_BR_CAP; flw_ptr[1] = itu_encode_br_cap(flw_ptr+2, &ptr->br_cap); flw_ptr += flw_ptr[1] + 2; } } //if(ptr->chnl_id.pres == 1) { flw_ptr[0] = IE_CHNL_ID; if(variant == VARIANT_QSIG) flw_ptr[1] = qsig_encode_chnl_id(flw_ptr+2, &ptr->chnl_id); else flw_ptr[1] = isdn_encode_chnl_id(flw_ptr+2, &ptr->chnl_id); flw_ptr += flw_ptr[1] + 2; } if(variant == VARIANT_ITU) { if(ptr->prg_ind.pres == 1) { flw_ptr[0] = IE_PRG_IND; flw_ptr[1] = isdn_encode_prg_ind(flw_ptr+2, &ptr->prg_ind); flw_ptr += flw_ptr[1] + 2; } if(ptr->disp.pres == 1) { flw_ptr[0] = IE_DISP; flw_ptr[1] = isdn_encode_disp(flw_ptr+2, &ptr->disp); flw_ptr += flw_ptr[1] + 2; } if(ptr->hl_comp.pres == 1) { flw_ptr[0] = IE_HL_COMP; flw_ptr[1] = isdn_encode_hl_comp(flw_ptr+2, &ptr->hl_comp); flw_ptr += flw_ptr[1] + 2; } } return flw_ptr - dst; } int isdn_decode_call_proc(IsdnMsgStr *dst, u8 *src, int variant, u8 len) { IsdnCallProc *ptr = &dst->msg_list.callProc; u8 *flw_ptr = src; u8 ie_m = 0; int ret = 0; while(flw_ptr+2-src <= len) { if(*flw_ptr == 0) { if(ie_m != 1) { printf("mandatory ie is absent!\n"); return 3; } break; } switch(*flw_ptr) { case IE_BR_CAP: if(variant == VARIANT_ITU) itu_decode_br_cap(&ptr->br_cap, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; case IE_CHNL_ID: //M if(variant == VARIANT_QSIG) ret = qsig_decode_chnl_id(&ptr->chnl_id, flw_ptr+2, flw_ptr[1]); else ret = isdn_decode_chnl_id(&ptr->chnl_id, flw_ptr+2, flw_ptr[1]); if(!ret) { printf("mandatory ie is err!\n"); return 2; } ie_m++; flw_ptr += flw_ptr[1] + 2; break; case IE_PRG_IND: if(variant == VARIANT_ITU) isdn_decode_prg_ind(&ptr->prg_ind, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; case IE_DISP: if(variant == VARIANT_ITU) isdn_decode_disp(&ptr->disp, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; case IE_HL_COMP: if(variant == VARIANT_ITU) isdn_decode_hl_comp(&ptr->hl_comp, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; default: if(*flw_ptr >= 0x80) //single octet IE flw_ptr += 1; else flw_ptr += flw_ptr[1] + 2; break; } } if(ie_m != 1) { printf("mandatory ie is absent!\n"); return 3; } return ISDN_CM_OK; } static int isdn_encode_conn(u8 *dst, IsdnMsgStr *src, int variant) { IsdnConn *ptr = &src->msg_list.conn; u8 *flw_ptr = dst; //Optional if(variant == VARIANT_ITU) { if(ptr->br_cap.pres == 1) { flw_ptr[0] = IE_BR_CAP; flw_ptr[1] = itu_encode_br_cap(flw_ptr+2, &ptr->br_cap); flw_ptr += flw_ptr[1] + 2; } } if(ptr->chnl_id.pres == 1) { flw_ptr[0] = IE_CHNL_ID; if(variant == VARIANT_QSIG) flw_ptr[1] = qsig_encode_chnl_id(flw_ptr+2, &ptr->chnl_id); else flw_ptr[1] = isdn_encode_chnl_id(flw_ptr+2, &ptr->chnl_id); flw_ptr += flw_ptr[1] + 2; } if(ptr->prg_ind.pres == 1) { flw_ptr[0] = IE_PRG_IND; flw_ptr[1] = isdn_encode_prg_ind(flw_ptr+2, &ptr->prg_ind); flw_ptr += flw_ptr[1] + 2; } if(variant == VARIANT_ITU) { if(ptr->disp.pres == 1) { flw_ptr[0] = IE_DISP; flw_ptr[1] = isdn_encode_disp(flw_ptr+2, &ptr->disp); flw_ptr += flw_ptr[1] + 2; } if(ptr->dt_time.pres == 1) { flw_ptr[0] = IE_DT_TIME; flw_ptr[1] = isdn_encode_dt_time(flw_ptr+2, &ptr->dt_time); flw_ptr += flw_ptr[1] + 2; } if(ptr->sign.pres == 1) { flw_ptr[0] = IE_SIGN; flw_ptr[1] = isdn_encode_sign(flw_ptr+2, &ptr->sign); flw_ptr += flw_ptr[1] + 2; } if(ptr->ll_comp.pres == 1) { flw_ptr[0] = IE_LL_COMP; flw_ptr[1] = isdn_encode_ll_comp(flw_ptr+2, &ptr->ll_comp); flw_ptr += flw_ptr[1] + 2; } if(ptr->hl_comp.pres == 1) { flw_ptr[0] = IE_HL_COMP; flw_ptr[1] = isdn_encode_hl_comp(flw_ptr+2, &ptr->hl_comp); flw_ptr += flw_ptr[1] + 2; } } else if(variant == VARIANT_QSIG) { if(ptr->conn_num.pres == 1) { flw_ptr[0] = IE_CONN_NUM; flw_ptr[1] = qsig_encode_conn_num(flw_ptr+2, &ptr->conn_num); flw_ptr += flw_ptr[1] + 2; } if(ptr->ll_comp.pres == 1) { flw_ptr[0] = IE_LL_COMP; flw_ptr[1] = isdn_encode_ll_comp(flw_ptr+2, &ptr->ll_comp); flw_ptr += flw_ptr[1] + 2; } } return flw_ptr - dst; } int isdn_decode_conn(IsdnMsgStr *dst, u8 *src, int variant, u8 len) { IsdnConn *ptr = &dst->msg_list.conn; u8 *flw_ptr = src; while(flw_ptr+2-src <= len) { if(*flw_ptr == 0) { break; } switch(*flw_ptr) { case IE_BR_CAP: if(variant == VARIANT_ITU) itu_decode_br_cap(&ptr->br_cap, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; case IE_CHNL_ID: if(variant == VARIANT_QSIG) qsig_decode_chnl_id(&ptr->chnl_id, flw_ptr+2, flw_ptr[1]); else isdn_decode_chnl_id(&ptr->chnl_id, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; case IE_PRG_IND: isdn_decode_prg_ind(&ptr->prg_ind, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; case IE_DISP: if(variant == VARIANT_ITU) isdn_decode_disp(&ptr->disp, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; case IE_DT_TIME: if(variant == VARIANT_ITU) isdn_decode_dt_time(&ptr->dt_time, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; case IE_SIGN: if(variant == VARIANT_ITU) isdn_decode_sign(&ptr->sign, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; case IE_CONN_NUM: if(variant == VARIANT_QSIG) qsig_decode_conn_num(&ptr->conn_num, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; case IE_LL_COMP: if(variant == VARIANT_ITU || variant == VARIANT_QSIG) isdn_decode_ll_comp(&ptr->ll_comp, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; case IE_HL_COMP: if(variant == VARIANT_ITU) isdn_decode_hl_comp(&ptr->hl_comp, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; default: if(*flw_ptr >= 0x80) //single octet IE flw_ptr += 1; else flw_ptr += flw_ptr[1] + 2; break; } } return ISDN_CM_OK; } static int isdn_encode_conn_ack(u8 *dst, IsdnMsgStr *src, int variant) { IsdnConnAck *ptr = &src->msg_list.connAck; u8 *flw_ptr = dst; //Optional if(variant == VARIANT_ITU) { if(ptr->disp.pres == 1) { flw_ptr[0] = IE_DISP; flw_ptr[1] = isdn_encode_disp(flw_ptr+2, &ptr->disp); flw_ptr += flw_ptr[1] + 2; } if(ptr->sign.pres == 1) { flw_ptr[0] = IE_SIGN; flw_ptr[1] = isdn_encode_sign(flw_ptr+2, &ptr->sign); flw_ptr += flw_ptr[1] + 2; } } return flw_ptr - dst; } int isdn_decode_conn_ack(IsdnMsgStr *dst, u8 *src, int variant, u8 len) { IsdnConnAck *ptr = &dst->msg_list.connAck; u8 *flw_ptr = src; while(flw_ptr+2-src <= len) { if(*flw_ptr == 0) { break; } switch(*flw_ptr) { case IE_DISP: if(variant == VARIANT_ITU) isdn_decode_disp(&ptr->disp, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; case IE_SIGN: if(variant == VARIANT_ITU) isdn_decode_sign(&ptr->sign, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; default: if(*flw_ptr >= 0x80) //single octet IE flw_ptr += 1; else flw_ptr += flw_ptr[1] + 2; break; } } return ISDN_CM_OK; } static int isdn_encode_prog(u8 *dst, IsdnMsgStr *src, int variant) { IsdnProg *ptr = &src->msg_list.prog; u8 *flw_ptr = dst; //Optional if(variant == VARIANT_ITU) { if(ptr->br_cap.pres == 1) { flw_ptr[0] = IE_BR_CAP; flw_ptr[1] = itu_encode_br_cap(flw_ptr+2, &ptr->br_cap); flw_ptr += flw_ptr[1] + 2; } } if(ptr->cause.pres == 1) { flw_ptr[0] = IE_CAUSE; flw_ptr[1] = isdn_encode_cause(flw_ptr+2, &ptr->cause); flw_ptr += flw_ptr[1] + 2; } //Mandatory if(ptr->prg_ind.pres == 1) { flw_ptr[0] = IE_PRG_IND; flw_ptr[1] = isdn_encode_prg_ind(flw_ptr+2, &ptr->prg_ind); flw_ptr += flw_ptr[1] + 2; } //Optional if(variant == VARIANT_ITU) { if(ptr->disp.pres == 1) { flw_ptr[0] = IE_DISP; flw_ptr[1] = isdn_encode_disp(flw_ptr+2, &ptr->disp); flw_ptr += flw_ptr[1] + 2; } if(ptr->hl_comp.pres == 1) { flw_ptr[0] = IE_HL_COMP; flw_ptr[1] = isdn_encode_hl_comp(flw_ptr+2, &ptr->hl_comp); flw_ptr += flw_ptr[1] + 2; } } return flw_ptr - dst; } int isdn_decode_prog(IsdnMsgStr *dst, u8 *src, int variant, u8 len) { IsdnProg *ptr = &dst->msg_list.prog; u8 *flw_ptr = src; u8 ie_m = 0; while(flw_ptr+2-src <= len) { if(*flw_ptr == 0) { if(ie_m != 1) { printf("mandatory ie is absent!\n"); return 3; } break; } switch(*flw_ptr) { case IE_BR_CAP: if(variant == VARIANT_ITU) itu_decode_br_cap(&ptr->br_cap, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; case IE_CAUSE: isdn_decode_cause(&ptr->cause, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; case IE_PRG_IND: //M if(!(isdn_decode_prg_ind(&ptr->prg_ind, flw_ptr+2, flw_ptr[1]))) { printf("mandatory ie is err!\n"); return 2; } ie_m++; flw_ptr += flw_ptr[1] + 2; break; case IE_DISP: if(variant == VARIANT_ITU) isdn_decode_disp(&ptr->disp, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; case IE_HL_COMP: if(variant == VARIANT_ITU) isdn_decode_hl_comp(&ptr->hl_comp, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; default: if(*flw_ptr >= 0x80) //single octet IE flw_ptr += 1; else flw_ptr += flw_ptr[1] + 2; break; } } if(ie_m != 1) { printf("mandatory ie is absent!\n"); return 3; } return ISDN_CM_OK; } static int isdn_encode_setup(u8 *dst, IsdnMsgStr *src, int variant) { IsdnSetup *ptr = &src->msg_list.setup; u8 *flw_ptr = dst; //Optional if(variant == VARIANT_ITU || variant == VARIANT_QSIG) { if(ptr->sd_comp.pres == 1) { flw_ptr[0] = IE_SD_COMP; flw_ptr += 1; } } if(variant == VARIANT_ITU) { if(ptr->rpt_ind.pres == 1) { flw_ptr[0] = IE_RPT_IND; flw_ptr += 1; } } //Mandatory if(ptr->br_cap.pres == 1) { flw_ptr[0] = IE_BR_CAP; if(variant == VARIANT_ITU) flw_ptr[1] = itu_encode_br_cap(flw_ptr+2, &ptr->br_cap); else flw_ptr[1] = isdn_encode_br_cap(flw_ptr+2, &ptr->br_cap); flw_ptr += flw_ptr[1] + 2; } //if(ptr->chnl_id.pres == 1) //user side is optional but network side is mandatory { flw_ptr[0] = IE_CHNL_ID; if(variant == VARIANT_QSIG) flw_ptr[1] = qsig_encode_chnl_id(flw_ptr+2, &ptr->chnl_id); else flw_ptr[1] = isdn_encode_chnl_id(flw_ptr+2, &ptr->chnl_id); flw_ptr += flw_ptr[1] + 2; } //Optional if(ptr->prg_ind.pres == 1) { flw_ptr[0] = IE_PRG_IND; flw_ptr[1] = isdn_encode_prg_ind(flw_ptr+2, &ptr->prg_ind); flw_ptr += flw_ptr[1] + 2; } if(variant == VARIANT_ITU || variant == VARIANT_ANSI) { if(ptr->nt_sp_fac.pres == 1) { flw_ptr[0] = IE_NT_SP_FAC; flw_ptr[1] = isdn_encode_ntsp_fac(flw_ptr+2, &ptr->nt_sp_fac); flw_ptr += flw_ptr[1] + 2; } } if(variant == VARIANT_ITU) { if(ptr->disp.pres == 1) { flw_ptr[0] = IE_DISP; flw_ptr[1] = isdn_encode_disp(flw_ptr+2, &ptr->disp); flw_ptr += flw_ptr[1] + 2; } if(ptr->dt_time.pres == 1) { flw_ptr[0] = IE_DT_TIME; flw_ptr[1] = isdn_encode_dt_time(flw_ptr+2, &ptr->dt_time); flw_ptr += flw_ptr[1] + 2; } if(ptr->kpd_fac.pres == 1) { flw_ptr[0] = IE_KPD_FAC; flw_ptr[1] = isdn_encode_kpd_fac(flw_ptr+2, &ptr->kpd_fac); flw_ptr += flw_ptr[1] + 2; } if(ptr->sign.pres == 1) { flw_ptr[0] = IE_SIGN; flw_ptr[1] = isdn_encode_sign(flw_ptr+2, &ptr->sign); flw_ptr += flw_ptr[1] + 2; } } if(ptr->cg_pty_num.pres == 1) { flw_ptr[0] = IE_CG_PTY_NUM; flw_ptr[1] = isdn_encode_cg_num(flw_ptr+2, &ptr->cg_pty_num); flw_ptr += flw_ptr[1] + 2; } if(variant == VARIANT_ITU || variant == VARIANT_QSIG) { if(ptr->cg_pty_addr.pres == 1) { flw_ptr[0] = IE_CG_PTY_ADDR; flw_ptr[1] = isdn_encode_cg_addr(flw_ptr+2, &ptr->cg_pty_addr); flw_ptr += flw_ptr[1] + 2; } } if(ptr->cd_pty_num.pres == 1) { flw_ptr[0] = IE_CD_PTY_NUM; flw_ptr[1] = isdn_encode_cd_num(flw_ptr+2, &ptr->cd_pty_num); flw_ptr += flw_ptr[1] + 2; } if(variant == VARIANT_ITU || variant == VARIANT_QSIG) { if(ptr->cd_pty_addr.pres == 1) { flw_ptr[0] = IE_CD_PTY_ADDR; flw_ptr[1] = isdn_encode_cd_addr(flw_ptr+2, &ptr->cd_pty_addr); flw_ptr += flw_ptr[1] + 2; } } if(variant == VARIANT_ANSI) { if(ptr->redir_num.pres == 1) { flw_ptr[0] = IE_REDIR_NUM; flw_ptr[1] = ansi_encode_redir_num(flw_ptr+2, &ptr->redir_num); flw_ptr += flw_ptr[1] + 2; } } if(variant == VARIANT_ITU || variant == VARIANT_ANSI) { if(ptr->tran_nt_sel.pres == 1) { flw_ptr[0] = IE_TRAN_NT_SEL; flw_ptr[1] = isdn_encode_tran_sel(flw_ptr+2, &ptr->tran_nt_sel); flw_ptr += flw_ptr[1] + 2; } } if(variant == VARIANT_ITU || variant == VARIANT_QSIG) { if(ptr->ll_comp.pres == 1) { flw_ptr[0] = IE_LL_COMP; flw_ptr[1] = isdn_encode_ll_comp(flw_ptr+2, &ptr->ll_comp); flw_ptr += flw_ptr[1] + 2; } if(ptr->hl_comp.pres == 1) { flw_ptr[0] = IE_HL_COMP; flw_ptr[1] = isdn_encode_hl_comp(flw_ptr+2, &ptr->hl_comp); flw_ptr += flw_ptr[1] + 2; } } return flw_ptr - dst; } int isdn_decode_setup(IsdnMsgStr *dst, u8 *src, int variant, u8 len) { IsdnSetup *ptr = &dst->msg_list.setup; u8 *flw_ptr = src; u8 ie_m = 0; int ret = 0; int qsig_ie_m = 0; while(flw_ptr+1-src <= len) { if(*flw_ptr == 0) { if(ie_m != 1) { printf("mandatory ie is absent!\n"); return 3; } if(qsig_ie_m != 2 && variant != VARIANT_ITU) { printf("mandatory ie is absent!\n"); return 3; } break; } switch(*flw_ptr) { case IE_SD_COMP: if(variant == VARIANT_ITU || variant == VARIANT_QSIG) ptr->sd_comp.pres = 1; flw_ptr += 1; break; case IE_RPT_IND: if(variant == VARIANT_ITU) ptr->rpt_ind.pres = 1; flw_ptr += 1; break; case IE_BR_CAP: //M if(!itu_decode_br_cap(&ptr->br_cap, flw_ptr+2, flw_ptr[1])) { printf("mandatory ie is err!\n"); return 2; } ie_m++; flw_ptr += flw_ptr[1] + 2; break; case IE_CHNL_ID: //M if(variant == VARIANT_QSIG) ret = qsig_decode_chnl_id(&ptr->chnl_id, flw_ptr+2, flw_ptr[1]); else ret = isdn_decode_chnl_id(&ptr->chnl_id, flw_ptr+2, flw_ptr[1]); if(!ret) { printf("channel identification ie is err!\n"); return 2; } qsig_ie_m++; flw_ptr += flw_ptr[1] + 2; break; case IE_PRG_IND: isdn_decode_prg_ind(&ptr->prg_ind, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; case IE_NT_SP_FAC: if(variant == VARIANT_ITU || variant == VARIANT_ANSI) isdn_decode_ntsp_fac(&ptr->nt_sp_fac, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; case IE_DISP: if(variant == VARIANT_ITU) isdn_decode_disp(&ptr->disp, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; case IE_DT_TIME: if(variant == VARIANT_ITU) isdn_decode_dt_time(&ptr->dt_time, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; case IE_KPD_FAC: if(variant == VARIANT_ITU) isdn_decode_kpd_fac(&ptr->kpd_fac, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; case IE_SIGN: if(variant == VARIANT_ITU) isdn_decode_sign(&ptr->sign, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; case IE_CG_PTY_NUM: isdn_decode_cg_num(&ptr->cg_pty_num, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; case IE_CG_PTY_ADDR: if(variant == VARIANT_ITU || variant == VARIANT_QSIG) isdn_decode_cg_addr(&ptr->cg_pty_addr, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; case IE_CD_PTY_NUM: ret = isdn_decode_cd_num(&ptr->cd_pty_num, flw_ptr+2, flw_ptr[1]); if((!ret) && (variant != VARIANT_ITU)) { printf("called number ie is err!\n"); return 2; } qsig_ie_m++; flw_ptr += flw_ptr[1] + 2; break; case IE_CD_PTY_ADDR: if(variant == VARIANT_ITU || variant == VARIANT_QSIG) isdn_decode_cd_addr(&ptr->cd_pty_addr, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; case IE_REDIR_NUM: if(variant == VARIANT_ANSI) ansi_decode_redir_num(&ptr->redir_num, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; case IE_TRAN_NT_SEL: if(variant == VARIANT_ITU || variant == VARIANT_ANSI) isdn_decode_tran_sel(&ptr->tran_nt_sel, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; case IE_LL_COMP: if(variant == VARIANT_ITU || variant == VARIANT_QSIG) isdn_decode_ll_comp(&ptr->ll_comp, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; case IE_HL_COMP: if(variant == VARIANT_ITU || variant == VARIANT_QSIG) isdn_decode_hl_comp(&ptr->hl_comp, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; default: if(*flw_ptr >= 0x80) //single octet IE flw_ptr += 1; else flw_ptr += flw_ptr[1] + 2; break; } } if(ie_m != 1) { printf("mandatory ie is absent!\n"); return 3; } if(qsig_ie_m != 2 && variant != VARIANT_ITU) { printf("mandatory ie is absent!\n"); return 3; } return ISDN_CM_OK; } static int isdn_encode_setup_ack(u8 *dst, IsdnMsgStr *src, int variant) { IsdnSetupAck *ptr = &src->msg_list.setupAck; u8 *flw_ptr = dst; //Optional if(variant == VARIANT_ITU) { //if(ptr->chnl_id.pres == 1) { flw_ptr[0] = IE_CHNL_ID; flw_ptr[1] = isdn_encode_chnl_id(flw_ptr+2, &ptr->chnl_id); flw_ptr += flw_ptr[1] + 2; } if(ptr->prg_ind.pres == 1) { flw_ptr[0] = IE_PRG_IND; flw_ptr[1] = isdn_encode_prg_ind(flw_ptr+2, &ptr->prg_ind); flw_ptr += flw_ptr[1] + 2; } if(ptr->disp.pres == 1) { flw_ptr[0] = IE_DISP; flw_ptr[1] = isdn_encode_disp(flw_ptr+2, &ptr->disp); flw_ptr += flw_ptr[1] + 2; } if(ptr->sign.pres == 1) { flw_ptr[0] = IE_SIGN; flw_ptr[1] = isdn_encode_sign(flw_ptr+2, &ptr->sign); flw_ptr += flw_ptr[1] + 2; } } else if(variant == VARIANT_QSIG) { //if(ptr->chnl_id.pres == 1) { flw_ptr[0] = IE_CHNL_ID; flw_ptr[1] = qsig_encode_chnl_id(flw_ptr+2, &ptr->chnl_id); flw_ptr += flw_ptr[1] + 2; } } else { printf("encode: there isnot msg setup ack in ansi!\n"); return -1; } return flw_ptr - dst; } int isdn_decode_setup_ack(IsdnMsgStr *dst, u8 *src, int variant, u8 len) { IsdnSetupAck *ptr = &dst->msg_list.setupAck; u8 *flw_ptr = src; u8 ie_m = 0; int ret; while(flw_ptr+2-src <= len) { if(*flw_ptr == 0) { if(ie_m != 1) { printf("mandatory ie is absent!\n"); return 3; } break; } switch(*flw_ptr) { case IE_CHNL_ID: //M if(variant == VARIANT_QSIG) ret = qsig_decode_chnl_id(&ptr->chnl_id, flw_ptr+2, flw_ptr[1]); else ret = isdn_decode_chnl_id(&ptr->chnl_id, flw_ptr+2, flw_ptr[1]); if(!ret) { printf("mandatory ie is err!\n"); return 2; } ie_m++; flw_ptr += flw_ptr[1] + 2; break; case IE_PRG_IND: if(variant == VARIANT_ITU) isdn_decode_prg_ind(&ptr->prg_ind, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; case IE_DISP: if(variant == VARIANT_ITU) isdn_decode_disp(&ptr->disp, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; case IE_SIGN: if(variant == VARIANT_ITU) isdn_decode_sign(&ptr->sign, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; default: if(*flw_ptr >= 0x80) //single octet IE flw_ptr += 1; else flw_ptr += flw_ptr[1] + 2; break; } } if(ie_m != 1) { printf("mandatory ie is absent!\n"); return 3; } return ISDN_CM_OK; } static int isdn_encode_disc(u8 *dst, IsdnMsgStr *src, int variant) { IsdnDisc *ptr = &src->msg_list.disc; u8 *flw_ptr = dst; //Mandatory if(ptr->cause.pres == 1) { flw_ptr[0] = IE_CAUSE; flw_ptr[1] = isdn_encode_cause(flw_ptr+2, &ptr->cause); flw_ptr += flw_ptr[1] + 2; } //Optional if(variant == VARIANT_ITU) { if(ptr->prg_ind.pres == 1) { flw_ptr[0] = IE_PRG_IND; flw_ptr[1] = isdn_encode_prg_ind(flw_ptr+2, &ptr->prg_ind); flw_ptr += flw_ptr[1] + 2; } if(ptr->disp.pres == 1) { flw_ptr[0] = IE_DISP; flw_ptr[1] = isdn_encode_disp(flw_ptr+2, &ptr->disp); flw_ptr += flw_ptr[1] + 2; } if(ptr->sign.pres == 1) { flw_ptr[0] = IE_SIGN; flw_ptr[1] = isdn_encode_sign(flw_ptr+2, &ptr->sign); flw_ptr += flw_ptr[1] + 2; } } return flw_ptr - dst; } int isdn_decode_disc(IsdnMsgStr *dst, u8 *src, int variant, u8 len) { IsdnDisc *ptr = &dst->msg_list.disc; u8 *flw_ptr = src; u8 ie_m = 0; while(flw_ptr+2-src <= len) { if(*flw_ptr == 0) { if(ie_m != 1) { printf("mandatory ie is absent!\n"); return 3; } break; } switch(*flw_ptr) { case IE_CAUSE: if(!isdn_decode_cause(&ptr->cause, flw_ptr+2, flw_ptr[1])) { printf("mandatory ie is err!\n"); return 2; } ie_m++; flw_ptr += flw_ptr[1] + 2; break; case IE_PRG_IND: if(variant == VARIANT_ITU) isdn_decode_prg_ind(&ptr->prg_ind, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; case IE_DISP: if(variant == VARIANT_ITU) isdn_decode_disp(&ptr->disp, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; case IE_SIGN: if(variant == VARIANT_ITU) isdn_decode_sign(&ptr->sign, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; default: if(*flw_ptr >= 0x80) //single octet IE flw_ptr += 1; else flw_ptr += flw_ptr[1] + 2; break; } } if(ie_m != 1) { printf("mandatory ie is absent!\n"); return 3; } return ISDN_CM_OK; } static int isdn_encode_rel(u8 *dst, IsdnMsgStr *src, int variant) { IsdnRel *ptr = &src->msg_list.rel; u8 *flw_ptr = dst; //Optional // if(ptr->cause.pres == 1) { flw_ptr[0] = IE_CAUSE; flw_ptr[1] = isdn_encode_cause(flw_ptr+2, &ptr->cause); flw_ptr += flw_ptr[1] + 2; } if(variant == VARIANT_ITU) { if(ptr->disp.pres == 1) { flw_ptr[0] = IE_DISP; flw_ptr[1] = isdn_encode_disp(flw_ptr+2, &ptr->disp); flw_ptr += flw_ptr[1] + 2; } if(ptr->sign.pres == 1) { flw_ptr[0] = IE_SIGN; flw_ptr[1] = isdn_encode_sign(flw_ptr+2, &ptr->sign); flw_ptr += flw_ptr[1] + 2; } } return flw_ptr - dst; } int isdn_decode_rel(IsdnMsgStr *dst, u8 *src, int variant, u8 len) { IsdnRel *ptr = &dst->msg_list.rel; u8 *flw_ptr = src; u8 ie_m = 0; while(flw_ptr+2-src <= len) { if(*flw_ptr == 0) { if(ie_m != 1) { printf("mandatory ie is absent!\n"); return 3; } break; } switch(*flw_ptr) { case IE_CAUSE: if(!isdn_decode_cause(&ptr->cause, flw_ptr+2, flw_ptr[1])) { printf("mandatory ie is err!\n"); return 2; } ie_m++; flw_ptr += flw_ptr[1] + 2; break; case IE_DISP: if(variant == VARIANT_ITU) isdn_decode_disp(&ptr->disp, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; case IE_SIGN: if(variant == VARIANT_ITU) isdn_decode_sign(&ptr->sign, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; default: if(*flw_ptr >= 0x80) //single octet IE flw_ptr += 1; else flw_ptr += flw_ptr[1] + 2; break; } } return ISDN_CM_OK; } static int isdn_encode_rel_comp(u8 *dst, IsdnMsgStr *src, int variant) { IsdnRelComp *ptr = &src->msg_list.relComp; u8 *flw_ptr = dst; //Optional if(ptr->cause.pres == 1) { flw_ptr[0] = IE_CAUSE; flw_ptr[1] = isdn_encode_cause(flw_ptr+2, &ptr->cause); flw_ptr += flw_ptr[1] + 2; } if(variant == VARIANT_ITU) { if(ptr->disp.pres == 1) { flw_ptr[0] = IE_DISP; flw_ptr[1] = isdn_encode_disp(flw_ptr+2, &ptr->disp); flw_ptr += flw_ptr[1] + 2; } if(ptr->sign.pres == 1) { flw_ptr[0] = IE_SIGN; flw_ptr[1] = isdn_encode_sign(flw_ptr+2, &ptr->sign); flw_ptr += flw_ptr[1] + 2; } } return flw_ptr - dst; } int isdn_decode_rel_comp(IsdnMsgStr *dst, u8 *src, int variant, u8 len) { IsdnRelComp *ptr = &dst->msg_list.relComp; u8 *flw_ptr = src; while(flw_ptr+2-src <= len) { if(*flw_ptr == 0) { break; } switch(*flw_ptr) { case IE_CAUSE: isdn_decode_cause(&ptr->cause, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; case IE_DISP: if(variant == VARIANT_ITU) isdn_decode_disp(&ptr->disp, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; case IE_SIGN: if(variant == VARIANT_ITU) isdn_decode_sign(&ptr->sign, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; default: if(*flw_ptr >= 0x80) //single octet IE flw_ptr += 1; else flw_ptr += flw_ptr[1] + 2; break; } } return ISDN_CM_OK; } static int isdn_encode_restart(u8 *dst, IsdnMsgStr *src, int variant) { IsdnRestart *ptr = &src->msg_list.restart; u8 *flw_ptr = dst; //Optional if(ptr->chnl_id.pres == 1) { flw_ptr[0] = IE_CHNL_ID; flw_ptr[1] = isdn_encode_chnl_id(flw_ptr+2, &ptr->chnl_id); flw_ptr += flw_ptr[1] + 2; } if(variant == VARIANT_ITU) { if(ptr->disp.pres == 1) { flw_ptr[0] = IE_DISP; flw_ptr[1] = isdn_encode_disp(flw_ptr+2, &ptr->disp); flw_ptr += flw_ptr[1] + 2; } } //Mandatory if(ptr->restart_ind.pres == 1) { flw_ptr[0] = IE_RESTART_IND; flw_ptr[1] = isdn_encode_restart_ind(flw_ptr+2, &ptr->restart_ind); flw_ptr += flw_ptr[1] + 2; } return flw_ptr - dst; } int isdn_decode_restart(IsdnMsgStr *dst, u8 *src, int variant, u8 len) { IsdnRestart *ptr = &dst->msg_list.restart; u8 *flw_ptr = src; u8 ie_m = 0; while(flw_ptr+2-src <= len) { if(*flw_ptr == 0) { if(ie_m != 1) { printf("mandatory ie is absent!\n"); return 3; } break; } switch(*flw_ptr) { case IE_CHNL_ID: isdn_decode_chnl_id(&ptr->chnl_id, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; case IE_DISP: if(variant == VARIANT_ITU) isdn_decode_disp(&ptr->disp, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; case IE_RESTART_IND: if(!isdn_decode_restart_ind(&ptr->restart_ind, flw_ptr+2, flw_ptr[1])) { printf("mandatory ie is err!\n"); return 2; } ie_m++; flw_ptr += flw_ptr[1] + 2; break; default: if(*flw_ptr >= 0x80) //single octet IE flw_ptr += 1; else flw_ptr += flw_ptr[1] + 2; break; } } if(ie_m != 1) { printf("mandatory ie is absent!\n"); return 3; } return ISDN_CM_OK; } static int isdn_encode_rest_ack(u8 *dst, IsdnMsgStr *src, int variant) { IsdnRestAck *ptr = &src->msg_list.restAck; u8 *flw_ptr = dst; //Optional if(ptr->chnl_id.pres == 1) { flw_ptr[0] = IE_CHNL_ID; flw_ptr[1] = isdn_encode_chnl_id(flw_ptr+2, &ptr->chnl_id); flw_ptr += flw_ptr[1] + 2; } if(variant == VARIANT_ITU) { if(ptr->disp.pres == 1) { flw_ptr[0] = IE_DISP; flw_ptr[1] = isdn_encode_disp(flw_ptr+2, &ptr->disp); flw_ptr += flw_ptr[1] + 2; } } //Mandatory if(ptr->restart_ind.pres == 1) { flw_ptr[0] = IE_RESTART_IND; flw_ptr[1] = isdn_encode_restart_ind(flw_ptr+2, &ptr->restart_ind); flw_ptr += flw_ptr[1] + 2; } return flw_ptr - dst; } int isdn_decode_rest_ack(IsdnMsgStr *dst, u8 *src, int variant, u8 len) { IsdnRestAck *ptr = &dst->msg_list.restAck; u8 *flw_ptr = src; u8 ie_m = 0; while(flw_ptr+2-src <= len) { if(*flw_ptr == 0) { if(ie_m != 1) { printf("mandatory ie is absent!\n"); return 3; } break; } switch(*flw_ptr) { case IE_CHNL_ID: isdn_decode_chnl_id(&ptr->chnl_id, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; case IE_DISP: if(variant == VARIANT_ITU) isdn_decode_disp(&ptr->disp, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; case IE_RESTART_IND: if(!isdn_decode_restart_ind(&ptr->restart_ind, flw_ptr+2, flw_ptr[1])) { printf("mandatory ie is err!\n"); return 2; } ie_m++; flw_ptr += flw_ptr[1] + 2; break; default: if(*flw_ptr >= 0x80) //single octet IE flw_ptr += 1; else flw_ptr += flw_ptr[1] + 2; break; } } if(ie_m != 1) { printf("mandatory ie is absent!\n"); return 3; } return ISDN_CM_OK; } static int isdn_encode_info(u8 *dst, IsdnMsgStr *src, int variant) { IsdnInfo *ptr = &src->msg_list.info; u8 *flw_ptr = dst; //Optional if(ptr->sd_comp.pres == 1) { flw_ptr[0] = IE_SD_COMP; flw_ptr += 1; } if(variant == VARIANT_ITU) { if(ptr->disp.pres == 1) { flw_ptr[0] = IE_DISP; flw_ptr[1] = isdn_encode_disp(flw_ptr+2, &ptr->disp); flw_ptr += flw_ptr[1] + 2; } if(ptr->kpd_fac.pres == 1) { flw_ptr[0] = IE_KPD_FAC; flw_ptr[1] = isdn_encode_kpd_fac(flw_ptr+2, &ptr->kpd_fac); flw_ptr += flw_ptr[1] + 2; } if(ptr->sign.pres == 1) { flw_ptr[0] = IE_SIGN; flw_ptr[1] = isdn_encode_sign(flw_ptr+2, &ptr->sign); flw_ptr += flw_ptr[1] + 2; } } if(ptr->cd_pty_num.pres == 1) { flw_ptr[0] = IE_CD_PTY_NUM; flw_ptr[1] = isdn_encode_cd_num(flw_ptr+2, &ptr->cd_pty_num); flw_ptr += flw_ptr[1] + 2; } return flw_ptr - dst; } int isdn_decode_info(IsdnMsgStr *dst, u8 *src, int variant, u8 len) { IsdnInfo *ptr = &dst->msg_list.info; u8 *flw_ptr = src; while(flw_ptr+1-src <= len) { if(*flw_ptr == 0) { break; } switch(*flw_ptr) { case IE_SD_COMP: ptr->sd_comp.pres = 1; flw_ptr += 1; break; case IE_DISP: if(variant == VARIANT_ITU) isdn_decode_disp(&ptr->disp, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; case IE_KPD_FAC: if(variant == VARIANT_ITU) isdn_decode_kpd_fac(&ptr->kpd_fac, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; case IE_SIGN: if(variant == VARIANT_ITU) isdn_decode_sign(&ptr->sign, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; case IE_CD_PTY_NUM: isdn_decode_cd_num(&ptr->cd_pty_num, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; default: if(*flw_ptr >= 0x80) //single octet IE flw_ptr += 1; else flw_ptr += flw_ptr[1] + 2; break; } } return ISDN_CM_OK; } static int isdn_encode_noti(u8 *dst, IsdnMsgStr *src, int variant) { IsdnNoti *ptr = &src->msg_list.noti; u8 *flw_ptr = dst; //Mandatory //Optional if(variant == VARIANT_ITU) { if(ptr->br_cap.pres == 1) { flw_ptr[0] = IE_BR_CAP; flw_ptr[1] = itu_encode_br_cap(flw_ptr+2, &ptr->br_cap); flw_ptr += flw_ptr[1] + 2; } } //Mandatory if(ptr->notify_ind.pres == 1) { flw_ptr[0] = IE_NOTIFY_IND; flw_ptr[1] = isdn_encode_notify_ind(flw_ptr+2, &ptr->notify_ind); flw_ptr += flw_ptr[1] + 2; } //Optional if(variant == VARIANT_ITU) { if(ptr->disp.pres == 1) { flw_ptr[0] = IE_DISP; flw_ptr[1] = isdn_encode_disp(flw_ptr+2, &ptr->disp); flw_ptr += flw_ptr[1] + 2; } } return flw_ptr - dst; } int isdn_decode_noti(IsdnMsgStr *dst, u8 *src, int variant, u8 len) { IsdnNoti *ptr = &dst->msg_list.noti; u8 *flw_ptr = src; u8 ie_m = 0; while(flw_ptr+2-src <= len) { if(*flw_ptr == 0) { if(ie_m != 1) { printf("mandatory ie is absent!\n"); return 3; } break; } switch(*flw_ptr) { case IE_BR_CAP: if(variant == VARIANT_ITU) itu_decode_br_cap(&ptr->br_cap, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; case IE_NOTIFY_IND: if(!isdn_decode_notify_ind(&ptr->notify_ind, flw_ptr+2, flw_ptr[1])) { printf("mandatory ie is err!\n"); return 2; } ie_m++; flw_ptr += flw_ptr[1] + 2; break; case IE_DISP: if(variant == VARIANT_ITU) isdn_decode_disp(&ptr->disp, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; default: if(*flw_ptr >= 0x80) //single octet IE flw_ptr += 1; else flw_ptr += flw_ptr[1] + 2; break; } } if(ie_m != 1) { printf("mandatory ie is absent!\n"); return 3; } return ISDN_CM_OK; } static int isdn_encode_status(u8 *dst, IsdnMsgStr *src, int variant) { IsdnStatus *ptr = &src->msg_list.status; u8 *flw_ptr = dst; //Mandatory if(ptr->cause.pres == 1) { flw_ptr[0] = IE_CAUSE; flw_ptr[1] = isdn_encode_cause(flw_ptr+2, &ptr->cause); flw_ptr += flw_ptr[1] + 2; } //if(ptr->call_stat.pres == 1) { flw_ptr[0] = IE_CALL_STAT; flw_ptr[1] = isdn_encode_call_stat(flw_ptr+2, &ptr->call_stat); flw_ptr += flw_ptr[1] + 2; } //Optional if(variant == VARIANT_ITU) { if(ptr->disp.pres == 1) { flw_ptr[0] = IE_DISP; flw_ptr[1] = isdn_encode_disp(flw_ptr+2, &ptr->disp); flw_ptr += flw_ptr[1] + 2; } } return flw_ptr - dst; } int isdn_decode_status(IsdnMsgStr *dst, u8 *src, int variant, u8 len) { IsdnStatus *ptr = &dst->msg_list.status; u8 *flw_ptr = src; u8 ie_m = 0; while(flw_ptr+2-src <= len) { if(*flw_ptr == 0) { if(ie_m != 2) { printf("mandatory ie is absent!\n"); return 3; } break; } switch(*flw_ptr) { case IE_CAUSE: if(!isdn_decode_cause(&ptr->cause, flw_ptr+2, flw_ptr[1])) { printf("mandatory ie is err!\n"); return 2; } ie_m++; flw_ptr += flw_ptr[1] + 2; break; case IE_CALL_STAT: if(!isdn_decode_call_stat(&ptr->call_stat, flw_ptr+2, flw_ptr[1])) { printf("mandatory ie is err!\n"); return 2; } ie_m++; flw_ptr += flw_ptr[1] + 2; break; case IE_DISP: if(variant == VARIANT_ITU) isdn_decode_disp(&ptr->disp, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; default: if(*flw_ptr >= 0x80) //single octet IE flw_ptr += 1; else flw_ptr += flw_ptr[1] + 2; break; } } if(ie_m != 2) { printf("mandatory ie is absent!\n"); return 3; } return ISDN_CM_OK; } static int isdn_encode_stat_enq(u8 *dst, IsdnMsgStr *src, int variant) { IsdnStatEnq *ptr = &src->msg_list.statEnq; u8 *flw_ptr = dst; //Optional if(variant == VARIANT_ITU) { if(ptr->disp.pres == 1) { flw_ptr[0] = IE_DISP; flw_ptr[1] = isdn_encode_disp(flw_ptr+2, &ptr->disp); flw_ptr += flw_ptr[1] + 2; } } return flw_ptr - dst; } int isdn_decode_stat_enq(IsdnMsgStr *dst, u8 *src, int variant, u8 len) { IsdnStatEnq *ptr = &dst->msg_list.statEnq; u8 *flw_ptr = src; while(flw_ptr+2-src <= len) { if(*flw_ptr == 0) { break; } switch(*flw_ptr) { case IE_DISP: if(variant == VARIANT_ITU) isdn_decode_disp(&ptr->disp, flw_ptr+2, flw_ptr[1]); flw_ptr += flw_ptr[1] + 2; break; default: if(*flw_ptr >= 0x80) //single octet IE flw_ptr += 1; else flw_ptr += flw_ptr[1] + 2; break; } } return ISDN_CM_OK; } //maintenance messages ansi static int isdn_encode_service(u8 *dst, IsdnMsgStr *src) { IsdnService *ptr = &src->msg_list.service; u8 *flw_ptr = dst; //Mandatory if(ptr->chg_stat.pres) { flw_ptr[0] = IE_CHG_STAT; flw_ptr[1] = ansi_encode_chg_stat(flw_ptr+2, &ptr->chg_stat); flw_ptr += flw_ptr[1] + 2; } //if(ptr->chnl_id.pres) { flw_ptr[0] = IE_CHNL_ID; flw_ptr[1] = isdn_encode_chnl_id(flw_ptr+2, &ptr->chnl_id); flw_ptr += flw_ptr[1] + 2; } return flw_ptr - dst; } int isdn_decode_service(IsdnMsgStr *dst, u8 *src, u8 len) { IsdnService *ptr = &dst->msg_list.service; u8 *flw_ptr = src; u8 ie_m = 0; while(flw_ptr+2-src <= len) { if(*flw_ptr == 0) { if(ie_m != 2) { printf("mandatory ie is absent!\n"); return 3; } break; } switch(*flw_ptr) { case IE_CHG_STAT: if(!ansi_decode_chg_stat(&ptr->chg_stat, flw_ptr+2, flw_ptr[1])) { printf("mandatory ie is err!\n"); return 2; } ie_m++; flw_ptr += flw_ptr[1] + 2; break; case IE_CHNL_ID: if(!isdn_decode_chnl_id(&ptr->chnl_id, flw_ptr+2, flw_ptr[1])) { printf("mandatory ie is err!\n"); return 2; } ie_m++; flw_ptr += flw_ptr[1] + 2; break; default: if(*flw_ptr >= 0x80) //single octet IE flw_ptr += 1; else flw_ptr += flw_ptr[1] + 2; break; } } if(ie_m != 2) { printf("mandatory ie is absent!\n"); return 3; } return ISDN_CM_OK; } static int isdn_encode_servAck(u8 *dst, IsdnMsgStr *src) { IsdnServAck *ptr = &src->msg_list.servAck; u8 *flw_ptr = dst; //Mandatory if(ptr->chg_stat.pres) { flw_ptr[0] = IE_CHG_STAT; flw_ptr[1] = ansi_encode_chg_stat(flw_ptr+2, &ptr->chg_stat); flw_ptr += flw_ptr[1] + 2; } //if(ptr->chnl_id.pres) { flw_ptr[0] = IE_CHNL_ID; flw_ptr[1] = isdn_encode_chnl_id(flw_ptr+2, &ptr->chnl_id); flw_ptr += flw_ptr[1] + 2; } return flw_ptr - dst; } int isdn_decode_servAck(IsdnMsgStr *dst, u8 *src, u8 len) { IsdnServAck *ptr = &dst->msg_list.servAck; u8 *flw_ptr = src; u8 ie_m = 0; while(flw_ptr+2-src <= len) { if(*flw_ptr == 0) { if(ie_m != 2) { printf("mandatory ie is absent!\n"); return 3; } break; } switch(*flw_ptr) { case IE_CHG_STAT: if(!ansi_decode_chg_stat(&ptr->chg_stat, flw_ptr+2, flw_ptr[1])) { printf("mandatory ie is err!\n"); return 2; } ie_m++; flw_ptr += flw_ptr[1] + 2; break; case IE_CHNL_ID: if(!isdn_decode_chnl_id(&ptr->chnl_id, flw_ptr+2, flw_ptr[1])) { printf("mandatory ie is err!\n"); return 2; } ie_m++; flw_ptr += flw_ptr[1] + 2; break; default: if(*flw_ptr >= 0x80) //single octet IE flw_ptr += 1; else flw_ptr += flw_ptr[1] + 2; break; } } if(ie_m != 2) { printf("mandatory ie is absent!\n"); return 3; } return ISDN_CM_OK; } /************************************************************* Function: itu_msg_encode Description: encode ITU isdn message Output: dst:preserving destination, src:source msg structure Return: isdn msg length:success ISDN_CM_FAILED:failed *************************************************************/ int itu_msg_encode(u8 *dst, IsdnMsgStr *src) //msg from isdn to iua { switch(src->msg_m.msg_type) { // case MSG_ALERT: return isdn_encode_alert(dst, src, VARIANT_ITU); case MSG_CALL_PROC: return isdn_encode_call_proc(dst, src, VARIANT_ITU); case MSG_CONN: return isdn_encode_conn(dst, src, VARIANT_ITU); case MSG_CONNACK: return isdn_encode_conn_ack(dst, src, VARIANT_ITU); case MSG_PROG: return isdn_encode_prog(dst, src, VARIANT_ITU); case MSG_SETUP: return isdn_encode_setup(dst, src, VARIANT_ITU); case MSG_SETUP_ACK: return isdn_encode_setup_ack(dst, src, VARIANT_ITU); // case MSG_DISC: return isdn_encode_disc(dst, src, VARIANT_ITU); case MSG_REL: return isdn_encode_rel(dst, src, VARIANT_ITU); case MSG_REL_COMP: return isdn_encode_rel_comp(dst, src, VARIANT_ITU); case MSG_RESTART: return isdn_encode_restart(dst, src, VARIANT_ITU); case MSG_REST_ACK: return isdn_encode_rest_ack(dst, src, VARIANT_ITU); // case MSG_INFORMATION: return isdn_encode_info(dst, src, VARIANT_ITU); case MSG_NOTI: return isdn_encode_noti(dst, src, VARIANT_ITU); case MSG_STATUS: return isdn_encode_status(dst, src, VARIANT_ITU); case MSG_STAT_ENQ: return isdn_encode_stat_enq(dst, src, VARIANT_ITU); default: break; } return -1; } /************************************************************* Function: itu_msg_decode Description: decode ITU isdn message Input: msgtype:msg type, len:msg length Output: dst:preserving destination structure, src:source msg code stream Return: ISDN_CM_OK:success ISDN_CM_FAILED or 2 or 3:failed *************************************************************/ int itu_msg_decode(IsdnMsgStr *dst, u8 *src, u8 msgtype, u8 len) //msg from iua to isdn { u8 msg_clas, msg_type; msg_clas = (msgtype & 0x60) >> 5; msg_type = (msgtype & 0x1F); switch(msg_clas) { case 0x0: // switch(msg_type) { case (MSG_ALERT & 0x1F): return isdn_decode_alert(dst, src, VARIANT_ITU, len); case (MSG_CALL_PROC & 0x1F): return isdn_decode_call_proc(dst, src, VARIANT_ITU, len); case (MSG_CONN & 0x1F): return isdn_decode_conn(dst, src, VARIANT_ITU, len); case (MSG_CONNACK & 0x1F): return isdn_decode_conn_ack(dst, src, VARIANT_ITU, len); case (MSG_PROG & 0x1F): return isdn_decode_prog(dst, src, VARIANT_ITU, len); case (MSG_SETUP & 0x1F): return isdn_decode_setup(dst, src, VARIANT_ITU, len); case (MSG_SETUP_ACK & 0x1F): return isdn_decode_setup_ack(dst, src, VARIANT_ITU, len); default: break; } break; case 0x1: // break; case 0x2: // switch(msg_type) { case (MSG_DISC & 0x1F): return isdn_decode_disc(dst, src, VARIANT_ITU, len); case (MSG_REL & 0x1F): return isdn_decode_rel(dst, src, VARIANT_ITU, len); case (MSG_REL_COMP & 0x1F): return isdn_decode_rel_comp(dst, src, VARIANT_ITU, len); case (MSG_RESTART & 0x1F): return isdn_decode_restart(dst, src, VARIANT_ITU, len); case (MSG_REST_ACK & 0x1F): return isdn_decode_rest_ack(dst, src, VARIANT_ITU, len); default: break; } break; case 0x3: // switch(msg_type) { case (MSG_INFORMATION & 0x1F): return isdn_decode_info(dst, src, VARIANT_ITU, len); case (MSG_NOTI & 0x1F): return isdn_decode_noti(dst, src, VARIANT_ITU, len); case (MSG_STATUS & 0x1F): return isdn_decode_status(dst, src, VARIANT_ITU, len); case (MSG_STAT_ENQ & 0x1F): return isdn_decode_stat_enq(dst, src, VARIANT_ITU, len); default: break; } break; default: break; } return ISDN_CM_FAILED; } int ansi_msg_encode(u8 *dst, IsdnMsgStr *src) //msg from isdn to iua { switch(src->msg_m.msg_type) { // case MSG_ALERT: return isdn_encode_alert(dst, src, VARIANT_ANSI); case MSG_CALL_PROC: return isdn_encode_call_proc(dst, src, VARIANT_ANSI); case MSG_CONN: return isdn_encode_conn(dst, src, VARIANT_ANSI); case MSG_CONNACK: return isdn_encode_conn_ack(dst, src, VARIANT_ANSI); case MSG_PROG: return isdn_encode_prog(dst, src, VARIANT_ANSI); case MSG_SETUP: return isdn_encode_setup(dst, src, VARIANT_ANSI); // case MSG_DISC: return isdn_encode_disc(dst, src, VARIANT_ANSI); case MSG_REL: return isdn_encode_rel(dst, src, VARIANT_ANSI); case MSG_REL_COMP: return isdn_encode_rel_comp(dst, src, VARIANT_ANSI); case MSG_RESTART: return isdn_encode_restart(dst, src, VARIANT_ANSI); case MSG_REST_ACK: return isdn_encode_rest_ack(dst, src, VARIANT_ANSI); // case MSG_NOTI: return isdn_encode_noti(dst, src, VARIANT_ANSI); case MSG_STATUS: return isdn_encode_status(dst, src, VARIANT_ANSI); case MSG_STAT_ENQ: return isdn_encode_stat_enq(dst, src, VARIANT_ANSI); default: break; } return -1; } int ansi_msg_decode(IsdnMsgStr *dst, u8 *src, u8 msgtype, u8 len) //msg from iua to isdn { u8 msg_clas, msg_type; msg_clas = (msgtype & 0x60) >> 5; msg_type = (msgtype & 0x1F); switch(msg_clas) { case 0x0: // switch(msg_type) { case (MSG_ALERT & 0x1F): return isdn_decode_alert(dst, src, VARIANT_ANSI, len); case (MSG_CALL_PROC & 0x1F): return isdn_decode_call_proc(dst, src, VARIANT_ANSI, len); case (MSG_CONN & 0x1F): return isdn_decode_conn(dst, src, VARIANT_ANSI, len); case (MSG_CONNACK & 0x1F): return isdn_decode_conn_ack(dst, src, VARIANT_ANSI, len); case (MSG_PROG & 0x1F): return isdn_decode_prog(dst, src, VARIANT_ANSI, len); case (MSG_SETUP & 0x1F): return isdn_decode_setup(dst, src, VARIANT_ANSI, len); default: break; } break; case 0x1: // break; case 0x2: // switch(msg_type) { case (MSG_DISC & 0x1F): return isdn_decode_disc(dst, src, VARIANT_ANSI, len); case (MSG_REL & 0x1F): return isdn_decode_rel(dst, src, VARIANT_ANSI, len); case (MSG_REL_COMP & 0x1F): return isdn_decode_rel_comp(dst, src, VARIANT_ANSI, len); case (MSG_RESTART & 0x1F): return isdn_decode_restart(dst, src, VARIANT_ANSI, len); case (MSG_REST_ACK & 0x1F): return isdn_decode_rest_ack(dst, src, VARIANT_ANSI, len); default: break; } break; case 0x3: // switch(msg_type) { case (MSG_NOTI & 0x1F): return isdn_decode_noti(dst, src, VARIANT_ANSI, len); case (MSG_STATUS & 0x1F): return isdn_decode_status(dst, src, VARIANT_ANSI, len); case (MSG_STAT_ENQ & 0x1F): return isdn_decode_stat_enq(dst, src, VARIANT_ANSI, len); default: break; } break; default: break; } return ISDN_CM_FAILED; } int qsig_msg_encode(u8 *dst, IsdnMsgStr *src) //msg from isdn to iua { switch(src->msg_m.msg_type) { // case MSG_ALERT: return isdn_encode_alert(dst, src, VARIANT_QSIG); case MSG_CALL_PROC: return isdn_encode_call_proc(dst, src, VARIANT_QSIG); case MSG_CONN: return isdn_encode_conn(dst, src, VARIANT_QSIG); case MSG_CONNACK: return isdn_encode_conn_ack(dst, src, VARIANT_QSIG); case MSG_PROG: return isdn_encode_prog(dst, src, VARIANT_QSIG); case MSG_SETUP: return isdn_encode_setup(dst, src, VARIANT_QSIG); case MSG_SETUP_ACK: return isdn_encode_setup_ack(dst, src, VARIANT_QSIG); // case MSG_DISC: return isdn_encode_disc(dst, src, VARIANT_QSIG); case MSG_REL: return isdn_encode_rel(dst, src, VARIANT_QSIG); case MSG_REL_COMP: return isdn_encode_rel_comp(dst, src, VARIANT_QSIG); case MSG_RESTART: return isdn_encode_restart(dst, src, VARIANT_QSIG); case MSG_REST_ACK: return isdn_encode_rest_ack(dst, src, VARIANT_QSIG); // case MSG_INFORMATION: return isdn_encode_info(dst, src, VARIANT_QSIG); case MSG_STATUS: return isdn_encode_status(dst, src, VARIANT_QSIG); case MSG_STAT_ENQ: return isdn_encode_stat_enq(dst, src, VARIANT_QSIG); default: break; } return -1; } int qsig_msg_decode(IsdnMsgStr *dst, u8 *src, u8 msgtype, u8 len) //msg from iua to isdn { u8 msg_clas, msg_type; msg_clas = (msgtype & 0x60) >> 5; msg_type = (msgtype & 0x1F); switch(msg_clas) { case 0x0: // switch(msg_type) { case (MSG_ALERT & 0x1F): return isdn_decode_alert(dst, src, VARIANT_QSIG, len); case (MSG_CALL_PROC & 0x1F): return isdn_decode_call_proc(dst, src, VARIANT_QSIG, len); case (MSG_CONN & 0x1F): return isdn_decode_conn(dst, src, VARIANT_QSIG, len); case (MSG_CONNACK & 0x1F): return isdn_decode_conn_ack(dst, src, VARIANT_QSIG, len); case (MSG_PROG & 0x1F): return isdn_decode_prog(dst, src, VARIANT_QSIG, len); case (MSG_SETUP & 0x1F): return isdn_decode_setup(dst, src, VARIANT_QSIG, len); default: break; } break; case 0x1: // break; case 0x2: // switch(msg_type) { case (MSG_DISC & 0x1F): return isdn_decode_disc(dst, src, VARIANT_QSIG, len); case (MSG_REL & 0x1F): return isdn_decode_rel(dst, src, VARIANT_QSIG, len); case (MSG_REL_COMP & 0x1F): return isdn_decode_rel_comp(dst, src, VARIANT_QSIG, len); case (MSG_RESTART & 0x1F): return isdn_decode_restart(dst, src, VARIANT_QSIG, len); case (MSG_REST_ACK & 0x1F): return isdn_decode_rest_ack(dst, src, VARIANT_QSIG, len); default: break; } break; case 0x3: // switch(msg_type) { case (MSG_INFORMATION & 0x1F): return isdn_decode_info(dst, src, VARIANT_QSIG, len); case (MSG_STATUS & 0x1F): return isdn_decode_status(dst, src, VARIANT_QSIG, len); case (MSG_STAT_ENQ & 0x1F): return isdn_decode_stat_enq(dst, src, VARIANT_QSIG, len); default: break; } break; default: break; } return ISDN_CM_FAILED; } /************************************************************* Function: maintenance_msg_encode Description: encode ansi isdn maintenance message Output: dst:preserving destination, src:source msg structure Return: isdn msg length:success ISDN_CM_FAILED:failed *************************************************************/ int maintenance_msg_encode(u8 *dst, IsdnMsgStr *src) //msg from isdn to iua { switch(src->msg_m.msg_type) { case MSG_SERVICE: return isdn_encode_service(dst, src); case MSG_SERVICE_ACK: return isdn_encode_servAck(dst, src); default: break; } return -1; } /************************************************************* Function: maintenance_msg_decode Description: decode ansi isdn maintenance message Input: msgtype:msg type, len:msg length Output: dst:preserving destination structure, src:source msg code stream Return: ISDN_CM_OK:success ISDN_CM_FAILED or 2 or 3:failed *************************************************************/ int maintenance_msg_decode(IsdnMsgStr *dst, u8 *src, u8 msgtype, u8 len) //msg from iua to isdn { switch(msgtype) { case MSG_SERVICE: return isdn_decode_service(dst, src, len); case MSG_SERVICE_ACK: return isdn_decode_servAck(dst, src, len); default: break; } return ISDN_CM_FAILED; } void isdn_send_heartbeat(int link_id) { message_list msg_trans; memset(&msg_trans, 0, sizeof(message_list)); msg_trans.msgSrcPort = ISDN_IP_PORT; msg_trans.msgDstIP = isdn_rs.attrib.isdn_remote_ip; msg_trans.msgDstPort = ISDN_IP_PORT; msg_trans.msgLength = 3; msg_trans.msgContent[0] = 1; //type msg_trans.msgContent[1] = link_id; msg_trans.msgContent[2] = isdn_rs.link_pond[link_id].dc_status; if(iptrPlatPutMessage(msg_trans) == 0) isdn_log_err(0, "send heartbeat err!link id =%d, remote ip =%d, link status =%d \r\n", link_id, isdn_rs.attrib.isdn_remote_ip, isdn_rs.link_pond[link_id].dc_status); } void isdn_redirect_send(IuaMsgStr *iua_src, int type) { message_list msg_trans; memset(&msg_trans, 0, sizeof(message_list)); msg_trans.msgSrcPort = ISDN_IP_PORT; msg_trans.msgDstIP = isdn_rs.attrib.isdn_remote_ip; msg_trans.msgDstPort = ISDN_IP_PORT; msg_trans.msgLength = iua_src->msg_length + 5; msg_trans.msgContent[0] = type; memcpy(msg_trans.msgContent+1, &iua_src->msg_class, msg_trans.msgLength-1); monitor_isdn_msg(0, "RD=>", iua_src, COL_BLUE); if(iua_src->msgcontent.isdn_msg.msg_m.proto_Discr == PROTOCOL_DISCR) isdn_msg_csta(iua_src->msgcontent.isdn_msg.msg_m.msg_type, 2); if(iptrPlatPutMessage(msg_trans) == 0) isdn_log_err(0, "redirect send err! msg type =0x%02x\r\n",iua_src->msgcontent.isdn_msg.msg_m.msg_type); } int isdn_msg_encode(u8 *dst, IsdnMsgStr *src, int variant) //msg from isdn to iua { switch(variant) { case VARIANT_ITU: return itu_msg_encode(dst, src); case VARIANT_ANSI: return ansi_msg_encode(dst, src); case VARIANT_QSIG: return qsig_msg_encode(dst, src); default: break; } return -1; } /************************************************************* Function: isdn_msg_decode Description: decode isdn message Input: msgtype:msg type, len:msg length, variant:proto variant Output: dst:preserving destination structure, src:source msg code stream Return: ISDN_CM_OK:success ISDN_CM_FAILED or 2 or 3:failed *************************************************************/ int isdn_msg_decode(IsdnMsgStr *dst, u8 *src, u8 msgtype, int variant, u8 len) //msg from iua to isdn { switch(variant) { case VARIANT_ITU: return itu_msg_decode(dst, src, msgtype, len); case VARIANT_ANSI: return ansi_msg_decode(dst, src, msgtype, len); case VARIANT_QSIG: return qsig_msg_decode(dst, src, msgtype, len); default: break; } return -1; } /************************************************************* Function: isdn_msdc_proc Description: isdn Message Sending Control, msg from isdn to iua Input: pid:port id Output: iua_src:iua msg structure Return: NULL *************************************************************/ void isdn_msdc_proc(u32 pid, IuaMsgStr *iua_src) { int circuit_id, cg_id, ds_0, ds_1, d_chnl, i; const pal_circuit_struct *circuit_ptr = NULL; const pal_cg_struct *cg_ptr = NULL; circuit_id = pid /ISDN_CIRCUIT_CIC; circuit_ptr = pal_circuit_ptr(circuit_id); if(circuit_ptr == NULL) return; d_chnl = pid % ISDN_CIRCUIT_CIC; cg_id = circuit_ptr->cg_id; cg_ptr = pal_cg_ptr(cg_id); if(cg_ptr == NULL) return; if(cg_ptr->attrib.protocol != PROTO_ISDN) return; ds_0 = cg_ptr->attrib.nfas.prim_link; ds_1 = cg_ptr->attrib.nfas.backup_link; iua_src->msg_class = IUA_QPTM_MSG; if((cg_ptr->attrib.nfas.flag == NFAS_ENABLE) && (circuit_ptr->attrib.d_chnl != d_chnl)) { if(isdn_rs.link_pond[ds_0].dc_status == DS_IS) { iua_src->e1_no = ds_0; for(i = 0; i < PAL_MAX_CIRCUIT; i++) { circuit_ptr = pal_circuit_ptr(i); if(circuit_ptr == NULL) continue; if(circuit_ptr->cg_id != cg_id) continue; if((circuit_ptr->attrib.link_id == ds_0) && (isdn_rs.attrib.isdn_run_mode == ISDN_DUAL_MODE) && (isdn_rs.attrib.systemID != circuit_ptr->attrib.plat_id)) { monitor_isdn_msg(pid, "SD<=", iua_src, COL_WHITE); isdn_redirect_send(iua_src, 2); //send to another plat return; } } } else if(isdn_rs.link_pond[ds_1].dc_status == DS_IS) { iua_src->e1_no = ds_1; for(i = 0; i < PAL_MAX_CIRCUIT; i++) { circuit_ptr = pal_circuit_ptr(i); if(circuit_ptr == NULL) continue; if(circuit_ptr->cg_id != cg_id) continue; if((circuit_ptr->attrib.link_id == ds_1) && (isdn_rs.attrib.isdn_run_mode == ISDN_DUAL_MODE) && (isdn_rs.attrib.systemID != circuit_ptr->attrib.plat_id)) { monitor_isdn_msg(pid, "SD<=", iua_src, COL_WHITE); isdn_redirect_send(iua_src, 2); //send to another plat return; } } } else { isdn_log_err(pid, "no link is ds_is state!ds_0=%d, ds_0_status=%d, ds_1=%d, ds_1_status=%d\n", ds_0, isdn_rs.link_pond[ds_0].dc_status, ds_1, isdn_rs.link_pond[ds_1].dc_status); return; } } else iua_src->e1_no = circuit_ptr->attrib.link_id; monitor_isdn_msg(pid, "SD<=", iua_src, COL_WHITE); iua_src->msg_length = htons(iua_src->msg_length); if(iua_src->msgcontent.isdn_msg.msg_m.proto_Discr == PROTOCOL_DISCR) isdn_msg_csta(iua_src->msgcontent.isdn_msg.msg_m.msg_type, 1); if(put_xua_msg((xua_up_msg_t*)&iua_src->msg_class) == -1) isdn_log_err(pid, "send msg to iua err!msg class=%d,msg type=0x%02x\r\n", iua_src->msg_class, iua_src->msgcontent.isdn_msg.msg_m.msg_type); else isdn_rs.port_pond[pid].pre_send_msg = iua_src->msgcontent.isdn_msg.msg_m.msg_type; } /************************************************************* Function: isdn_send_msg Description: isdn send msg to iua, include encode msg Input: pid:port id, msg_type:msg type Return: ISDN_CM_OK:success ISDN_CM_FAILED:failed *************************************************************/ int isdn_send_msg(u32 pid, u8 msg_type) { u16 call_ref; u8 callout_fg; int ret, variant; IuaMsgStr *src = &iua_sd_msg; ISDN_Port_struct *pPort = &isdn_rs.port_pond[pid]; u8 *flw_ptr = src->msgcontent.isdn_msg.ie_content; //message flow pointer const pal_circuit_struct *circuit_ptr = NULL; const pal_cg_struct *cg_ptr = NULL; memset(src, 0, sizeof(IuaMsgStr)); call_ref = pPort->call_ref; callout_fg = pPort->callout_fg; circuit_ptr = pal_circuit_ptr(pid /ISDN_CIRCUIT_CIC); if(circuit_ptr == NULL) return ISDN_CM_FAILED; cg_ptr = pal_cg_ptr(circuit_ptr->cg_id); if(cg_ptr == NULL) return ISDN_CM_FAILED; if(cg_ptr->attrib.protocol != PROTO_ISDN) return ISDN_CM_FAILED; variant = cg_ptr->attrib.variant; isdn_sd_msg.msg_m.proto_Discr = PROTOCOL_DISCR; isdn_sd_msg.msg_m.cr_len = 2; isdn_sd_msg.msg_m.call_ref[0] = ((call_ref & 0x7F00) >> 8) | (callout_fg << 7); //High isdn_sd_msg.msg_m.call_ref[1] = (call_ref & 0xFF); //Low isdn_sd_msg.msg_m.msg_type = msg_type; ret = isdn_msg_encode(flw_ptr, &isdn_sd_msg, variant); if(ret == -1) { isdn_log_err(pid, "unknown msg encode, msg=0x%02x\r\n", msg_type); return ISDN_CM_FAILED; } memcpy(&src->msgcontent.isdn_msg.msg_m, &isdn_sd_msg.msg_m, sizeof(MsgMan)); src->msg_length = ret + 0x0005; isdn_msdc_proc(pid, src); return ISDN_CM_OK; } /************************************************************* Function: isdn_send_maintenance_msg Description: isdn send ansi isdn maintenance msg to iua, include encode msg Input: pid:port id, msg_type:msg type Return: ISDN_CM_OK:success ISDN_CM_FAILED:failed *************************************************************/ int isdn_send_maintenance_msg(u32 pid, u8 msg_type) { u16 call_ref; u8 callout_fg; int ret; IuaMsgStr *src = &iua_sd_msg; ISDN_Port_struct *pPort = &isdn_rs.port_pond[pid]; u8 *flw_ptr = src->msgcontent.isdn_msg.ie_content; //message flow pointer memset(src, 0, sizeof(IuaMsgStr)); call_ref = pPort->call_ref; callout_fg = pPort->callout_fg; isdn_sd_msg.msg_m.proto_Discr = M_PROTOCOL_DISCR; isdn_sd_msg.msg_m.cr_len = 2; isdn_sd_msg.msg_m.call_ref[0] = ((call_ref & 0x7F00) >> 8) | (callout_fg << 7); //High isdn_sd_msg.msg_m.call_ref[1] = (call_ref & 0xFF); //Low isdn_sd_msg.msg_m.msg_type = msg_type; ret = maintenance_msg_encode(flw_ptr, &isdn_sd_msg); if(ret == -1) { isdn_log_err(pid, "unknown msg encode, msg=0x%02x\r\n", msg_type); return ISDN_CM_FAILED; } memcpy(&src->msgcontent.isdn_msg.msg_m, &isdn_sd_msg.msg_m, sizeof(MsgMan)); src->msg_length = ret + 0x0005; isdn_msdc_proc(pid, src); return ISDN_CM_OK; } /************************************************************* Function: n0_ext_proc Description: reinforce to receive abnormity msg at null state Input: pid:port id, msg_type:msg type Return: NULL *************************************************************/ static inline void n0_ext_proc(u32 pid, u8 msg_type) { if(msg_type == MSG_REL_COMP) { isdn_log_err(pid, "receive rel_comp at null state , invalid call reference!\r\n"); return; } else if(msg_type == MSG_STAT_ENQ) { isdn_set_status(&isdn_sd_msg.msg_list.status, 0, CAUSE_STAT_ENQ); isdn_send_msg(pid, MSG_STATUS); isdn_log_err(pid, "receive stat_enq at null state, response status msg!\r\n"); return; } else if(msg_type == MSG_STATUS) { if(isdn_rv_msg.msg_list.status.call_stat.stat_val == 0) { isdn_log_err(pid, "receive status at null state, and indicate state value is 0!\r\n"); return; } isdn_set_cause(&isdn_sd_msg.msg_list.relComp.cause, CAUSE_MSG_NOTCOMP); //cause 101 } else //unknown or unexpected msg isdn_set_cause(&isdn_sd_msg.msg_list.relComp.cause, CAUSE_INVALID_CR); //cause 81, invalid call reference isdn_send_msg(pid, MSG_REL_COMP); isdn_log_err(pid, "invalid call reference!\r\n"); return; } /************************************************************* Function: setup_abn_ie Description: decode setup with abnormity information elements Input: pid:port id, ret:decode result Return: NULL *************************************************************/ static inline void setup_abn_ie(u32 pid, int ret) { if(ret == 3) { isdn_log_err(pid, "setup mandatory information element is absent!\r\n"); isdn_set_cause(&isdn_sd_msg.msg_list.relComp.cause, CAUSE_M_IE_MISS); } else if(ret == 2) { isdn_log_err(pid, "setup mandatory information element is err!\r\n"); isdn_set_cause(&isdn_sd_msg.msg_list.relComp.cause, CAUSE_IE_INVALID); } isdn_send_msg(pid, MSG_REL_COMP); rel_cr(pid); } /************************************************************* Function: isdn_mdsc_proc Description: isdn Message Distribution Control, msg from iua to isdn Input: NULL Return: ISDN_CM_OK:success ISDN_CM_FAILED:failed *************************************************************/ static int isdn_mdsc_proc() { u32 pid, cic, head_cic; u16 cref = 0; int msg_type, variant, cg_id, circuit_newId, link_id; u8 global_flag; int ret, len, i; const pal_circuit_struct *circuit_ptr = NULL; const pal_cg_struct *cg_ptr = NULL; u8 *flw_ptr; flw_ptr = iua_rv_msg.msgcontent.isdn_msg.ie_content; len = iua_rv_msg.msg_length - 5; isdn_msg_csta(iua_rv_msg.msgcontent.isdn_msg.msg_m.msg_type, 0); if(iua_rv_msg.msgcontent.isdn_msg.msg_m.cr_len != 2) { isdn_log_err(0, "call reference len is not 2!\r\n"); //dummy call reference monitor_isdn_msg(0, "RV=>", &iua_rv_msg,COL_YELLOW); return ISDN_CM_FAILED; } link_id = iua_rv_msg.e1_no; if((circuit_ptr = pal_isdn_find_circuit_of_link(link_id)) == NULL) { isdn_log_err(0, "mdsc: link_id %d is unknown link!\r\n", link_id); monitor_isdn_msg(0, "RV=>", &iua_rv_msg,COL_YELLOW); return ISDN_CM_FAILED; } // circuit_id = circuit_ptr->id; cg_id = circuit_ptr->cg_id; cg_ptr = pal_cg_ptr(cg_id); if(cg_ptr == NULL) return ISDN_CM_FAILED; if(cg_ptr->attrib.protocol != PROTO_ISDN) return ISDN_CM_FAILED; if(!(cg_ptr->attrib.variant == VARIANT_ITU || cg_ptr->attrib.variant == VARIANT_ANSI || cg_ptr->attrib.variant == VARIANT_QSIG) || (cg_ptr->attrib.variant == VARIANT_QSIG && (cg_ptr->attrib.nfas.flag || circuit_ptr->attrib.user_network_if == NETWORK_SIDE))) return ISDN_CM_FAILED; variant = cg_ptr->attrib.variant; cref = iua_rv_msg.msgcontent.isdn_msg.msg_m.call_ref[0]; cref = (cref << 8) | (iua_rv_msg.msgcontent.isdn_msg.msg_m.call_ref[1]); msg_type = iua_rv_msg.msgcontent.isdn_msg.msg_m.msg_type; memset(&isdn_sd_msg, 0, sizeof(IsdnMsgStr)); memset(&isdn_rv_msg, 0, sizeof(IsdnMsgStr)); if((cref & 0x7FFF) == 0) //Global call reference message { global_flag = 1; pid = circuit_ptr->id * ISDN_CIRCUIT_CIC; isdn_rs.port_pond[pid].call_ref = cref; isdn_rs.port_pond[pid].callout_fg = ((cref >> 15) ^ 0x01); if((msg_type != MSG_RESTART) && (msg_type != MSG_REST_ACK) && (msg_type != MSG_STATUS)) { isdn_log_err(0, "invalid call reference, cr = 0!\r\n"); isdn_set_status(&isdn_sd_msg.msg_list.status, 0, CAUSE_INVALID_CR); //cause 81, state? isdn_send_msg(pid, MSG_STATUS); return ISDN_CM_FAILED; } else if(msg_type == MSG_STATUS) { isdn_log_err(0, "receive status in cr=0, reserved in current state!\r\n"); return ISDN_CM_FAILED; } } else { global_flag = 0; if(cg_ptr->attrib.nfas.flag == NFAS_ENABLE) { if(isdn_rs.link_pond[link_id].dc_status != DS_IS) { isdn_log_err(0, "the link %d is not DS_IS state!\r\n", link_id); return ISDN_CM_FAILED; } for(i = 0; i < PAL_MAX_CIRCUIT; i++) { circuit_ptr = pal_circuit_ptr(i); if(circuit_ptr == NULL) continue; if(circuit_ptr->cg_id != cg_id) continue; if((circuit_ptr->enable) && (pid = find_port_by_callref(cref, i))) { // circuit_id = i; break; } } if((pid == 0) && (msg_type != MSG_SETUP) && (isdn_rs.attrib.isdn_run_mode == ISDN_DUAL_MODE) && (circuit_ptr->attrib.plat_id == isdn_rs.attrib.systemID)) { monitor_isdn_msg(0, "RV=>", &iua_rv_msg, COL_YELLOW); isdn_redirect_send(&iua_rv_msg, 3); //send to another plat return ISDN_CM_FAILED; } } else pid = find_port_by_callref(cref, circuit_ptr->id); } memcpy(&isdn_rv_msg.msg_m, &iua_rv_msg.msgcontent.isdn_msg.msg_m, sizeof(MsgMan)); ret = isdn_msg_decode(&isdn_rv_msg, flw_ptr, msg_type, variant, len); if((pid == 0) && (global_flag == 0)) { if(msg_type != MSG_SETUP) //NULL STATE of other proc { isdn_log_err(0, "receice msg=0x%02x, when port id is 0!\r\n", msg_type); pid = circuit_ptr->id * ISDN_CIRCUIT_CIC; isdn_rs.port_pond[pid].call_ref = cref; isdn_rs.port_pond[pid].callout_fg = ((cref >> 15) ^ 0x01); n0_ext_proc(pid, msg_type); return ISDN_CM_FAILED; } else if((cref & 0x8000) != 0) { isdn_log_err(0, "the call reference is not from the original call!\r\n"); return ISDN_CM_FAILED; } //else goto setup to find port id } if(ret == 0) { isdn_log_err(pid, "decode isdn msg is unknown! msg=0x%02x\r\n",msg_type); isdn_set_status(&isdn_sd_msg.msg_list.status, isdn_rs.port_pond[pid].fsm_state.cpc_state, CAUSE_MSG_NOTCOMP_NOTIMPL); //cause 97 or 98 u01-04 isdn_send_msg(pid, MSG_STATUS); return ISDN_CM_FAILED; } else if(ret == -1) { isdn_log_err(pid, "unknown protocol discriminator! proto_discr=%d\r\n", iua_rv_msg.msgcontent.isdn_msg.msg_m.proto_Discr); return ISDN_CM_FAILED; } switch(msg_type) { case MSG_SETUP: if(pid != 0) { isdn_log_err(0, "setup has reveived! pid=%d\r\n", pid); return ISDN_CM_FAILED; } if(ret != 1) { pid = circuit_ptr->id * ISDN_CIRCUIT_CIC; isdn_rs.port_pond[pid].call_ref = cref; isdn_rs.port_pond[pid].callout_fg = ((cref >> 15) ^ 0x01); setup_abn_ie(pid, ret); return ISDN_CM_FAILED; } if(cg_ptr->attrib.nfas.flag) { if((isdn_rv_msg.msg_list.setup.chnl_id.pres) && (isdn_rv_msg.msg_list.setup.chnl_id.b3.int_id_pre)) { if((circuit_newId = find_circuit_by_interfaceId(cg_id, isdn_rv_msg.msg_list.setup.chnl_id.b3.int_id)) == -1) { if(circuit_ptr->attrib.plat_id == isdn_rs.attrib.systemID) { monitor_isdn_msg(0, "RV=>", &iua_rv_msg, COL_YELLOW); isdn_redirect_send(&iua_rv_msg, 3); //send to another plat return ISDN_CM_FAILED; } else { isdn_log_err(0, "not find current circuit! circuit id=%d\r\n", circuit_ptr->id); return ISDN_CM_FAILED; } } else { circuit_ptr = pal_circuit_ptr(circuit_newId); if(circuit_ptr == NULL) { isdn_log_err(0, "receive setup err! circuit_id=%d, can't find circuit_ptr!\r\n", circuit_newId); return ISDN_CM_FAILED; } if(circuit_ptr->cg_id != cg_id) return ISDN_CM_FAILED; } } else { isdn_log_err(0, "err!\n"); return ISDN_CM_FAILED; } } if((isdn_rv_msg.msg_list.setup.chnl_id.pres) && (isdn_rv_msg.msg_list.setup.chnl_id.b3.int_type)) { head_cic = circuit_ptr->attrib.head_cic; if(circuit_ptr->attrib.cic_range == 24) head_cic--; cic = head_cic + isdn_rv_msg.msg_list.setup.chnl_id.b3.chnl_num; if((cic < circuit_ptr->attrib.head_cic) || (cic - circuit_ptr->attrib.head_cic) >= (circuit_ptr->attrib.cic_range)) { pid = circuit_ptr->id * ISDN_CIRCUIT_CIC; isdn_rs.port_pond[pid].call_ref = cref; isdn_rs.port_pond[pid].callout_fg = ((cref >> 15) ^ 0x01); isdn_set_cause(&isdn_sd_msg.msg_list.relComp.cause, CAUSE_IE_INVALID); isdn_send_msg(pid, MSG_REL_COMP); isdn_log_err(0, "decode cic err!cic=0x%04x\r\n",cic); return ISDN_CM_FAILED; } else //find pid by cic { pid = find_port_by_cic(cic, circuit_ptr->id); if(isdn_rs.port_pond[pid].cic_state.maintenance_state != IN_SERVICE) { isdn_log_err(pid, "this cic is not in service in receive setup!\n"); return ISDN_CM_FAILED; } if(isdn_rs.port_pond[pid].enable == 1) //priority { if(!cg_ptr->attrib.priority) { isdn_event_handle(pid, ISDN_REATTEMPT_IND); rel_cr(pid); isdn_cpc_clear(&isdn_rs.port_pond[pid]); } else return ISDN_CM_FAILED; } } } if(pid == 0) //assign new pid { if(cg_ptr->attrib.nfas.flag) { if(!isdn_rv_msg.msg_list.setup.chnl_id.b3.int_id_pre) { cic = msc_give_cic_value(cg_ptr->attrib.tg_id, -1); if((circuit_ptr = pal_locate_circuit(cg_id, cic)) == NULL) { isdn_log_err(0, "the assign cic is not found the adscription of circuit! cic=%, cg_id=%d\n",cic, cg_id); return ISDN_CM_FAILED; } } else cic = msc_give_cic_value(cg_ptr->attrib.tg_id, circuit_ptr->attrib.head_cic); } else cic = msc_give_cic_value(cg_ptr->attrib.tg_id, circuit_ptr->attrib.head_cic); pid = find_port_by_cic(cic, circuit_ptr->id); } isdn_rs.port_pond[pid].call_ref = cref; //msg_cref[pid] = cref; if(circuit_ptr->attrib.user_network_if) { isdn_rs.port_pond[pid].timer_flag |= CALLIN_FLAG; isdn_rs.port_pond[pid].cic_state.call_state = CALLIN_FLAG; } else { isdn_rs.port_pond[pid].timer_flag |= CALLOUT_FLAG; isdn_rs.port_pond[pid].cic_state.call_state = CALLOUT_FLAG; } isdn_rs.port_pond[pid].callout_fg = 1; isdn_rs.port_pond[pid].enable = 1; break; case MSG_DISC: if(ret == 3) { isdn_log_err(pid, "disc mandatory information element is absent!\r\n"); isdn_set_cause(&isdn_rv_msg.msg_list.disc.cause, CAUSE_M_IE_MISS); } else if(ret == 2) { isdn_log_err(pid, "disc mandatory information element is err!\r\n"); isdn_set_cause(&isdn_rv_msg.msg_list.disc.cause, CAUSE_IE_INVALID); } memcpy(&isdn_sd_msg.msg_list.rel.cause, &isdn_rv_msg.msg_list.disc.cause, sizeof(CauseStr)); break; case MSG_REL: if(ret == 3) //u03-18 u00-13 u07-12 { isdn_log_err(pid, "rel mandatory information element is absent!\r\n"); isdn_set_cause(&isdn_sd_msg.msg_list.relComp.cause, CAUSE_M_IE_MISS); memcpy(&isdn_rv_msg, &isdn_sd_msg, sizeof(IsdnMsgStr)); } else if(ret == 2) //u03-19 u00-14 u07-13 { isdn_log_err(pid, "rel mandatory information element is err!\r\n"); isdn_set_cause(&isdn_sd_msg.msg_list.relComp.cause, CAUSE_IE_INVALID); memcpy(&isdn_rv_msg, &isdn_sd_msg, sizeof(IsdnMsgStr)); } else memcpy(&isdn_sd_msg.msg_list.relComp.cause, &isdn_rv_msg.msg_list.rel.cause, sizeof(CauseStr)); break; case MSG_RESTART: case MSG_REST_ACK: if(msg_type == MSG_RESTART) { if(cg_ptr->attrib.nfas.flag) { if((isdn_rv_msg.msg_list.restart.chnl_id.pres) && (isdn_rv_msg.msg_list.restart.chnl_id.b3.int_id_pre)) { if((circuit_newId = find_circuit_by_interfaceId(cg_id, isdn_rv_msg.msg_list.restart.chnl_id.b3.int_id)) == -1) { if(circuit_ptr->attrib.plat_id == isdn_rs.attrib.systemID) { monitor_isdn_msg(0, "RV=>", &iua_rv_msg, COL_YELLOW); isdn_redirect_send(&iua_rv_msg, 3); //send to another plat return ISDN_CM_FAILED; } else { isdn_log_err(0, "not find current circuit! circuit id=%d\r\n", circuit_ptr->id); return ISDN_CM_FAILED; } } else { circuit_ptr = pal_circuit_ptr(circuit_newId); if(circuit_ptr == NULL) { isdn_log_err(0, "receive restart err! circuit_id=%d, can't find circuit_ptr!\r\n", circuit_newId); return ISDN_CM_FAILED; } if(circuit_ptr->cg_id != cg_id) return ISDN_CM_FAILED; } } else { isdn_log_err(0, "receive restart err!\n"); return ISDN_CM_FAILED; } } } else { if(cg_ptr->attrib.nfas.flag) { if((isdn_rv_msg.msg_list.restAck.chnl_id.pres) && (isdn_rv_msg.msg_list.restAck.chnl_id.b3.int_id_pre)) { if((circuit_newId = find_circuit_by_interfaceId(cg_id, isdn_rv_msg.msg_list.restAck.chnl_id.b3.int_id)) == -1) { if(circuit_ptr->attrib.plat_id == isdn_rs.attrib.systemID) { monitor_isdn_msg(0, "RV=>", &iua_rv_msg, COL_YELLOW); isdn_redirect_send(&iua_rv_msg, 3); //send to another plat return ISDN_CM_FAILED; } else { isdn_log_err(0, "not find current circuit! circuit id=%d\r\n", circuit_ptr->id); return ISDN_CM_FAILED; } } else { circuit_ptr = pal_circuit_ptr(circuit_newId); if(circuit_ptr == NULL) { isdn_log_err(0, "receive restart ack err! circuit_id=%d, can't find circuit_ptr!\r\n", circuit_newId); return ISDN_CM_FAILED; } if(circuit_ptr->cg_id != cg_id) return ISDN_CM_FAILED; } } else { isdn_log_err(0, "receive restart ack err!\n"); return ISDN_CM_FAILED; } } } pid = circuit_ptr->id * ISDN_CIRCUIT_CIC; head_cic = circuit_ptr->attrib.head_cic; if(circuit_ptr->attrib.cic_range == 24) head_cic--; isdn_rs.port_pond[pid].callout_fg = ((cref >> 15) ^ 0x01); isdn_rs.link_pond[circuit_ptr->attrib.link_id].restart_clas = isdn_rv_msg.msg_list.restart.restart_ind.clas; if(isdn_rs.link_pond[circuit_ptr->attrib.link_id].restart_clas == 0) isdn_rs.port_pond[pid].cic_val = head_cic + isdn_rv_msg.msg_list.restart.chnl_id.b3.chnl_num; default: //other if(ret == 3) { isdn_log_err(pid, "msg=0x%02x mandatory information element is absent!\r\n", msg_type); isdn_set_status(&isdn_sd_msg.msg_list.status, isdn_rs.port_pond[pid].fsm_state.cpc_state, CAUSE_M_IE_MISS); isdn_send_msg(pid, MSG_STATUS); return ISDN_CM_FAILED; } else if(ret == 2) { isdn_log_err(pid, "msg=0x%02x mandatory information element is err!\r\n",msg_type); isdn_set_status(&isdn_sd_msg.msg_list.status, isdn_rs.port_pond[pid].fsm_state.cpc_state, CAUSE_IE_INVALID); isdn_send_msg(pid, MSG_STATUS); return ISDN_CM_FAILED; } break; } monitor_isdn_msg(pid, "RV=>", &iua_rv_msg, COL_YELLOW); isdn_rs.port_pond[pid].msg_cmd = msg_type; if(global_flag) { isdn_restart_ctrl(pid); } else if((isdn_rs.port_pond[pid].cic_state.call_state == CALLOUT_FLAG) || (isdn_rs.port_pond[pid].cic_state.call_state == CALLIN_FLAG)) { isdn_cpc_proc(pid); } if(isdn_rs.port_pond[pid].msg_cmd != 0) { isdn_log_err(pid, "ignore the message! msg_cmd=0x%x\r\n", isdn_rs.port_pond[pid].msg_cmd); isdn_rs.port_pond[pid].msg_cmd = 0; } return ISDN_CM_OK; } static int isdn_m_mdsc_proc() { u32 pid, cic, head_cic; u16 cref = 0; u8 msg_type, link_id; int ret, len, cg_id, circuit_newId; const pal_circuit_struct *circuit_ptr = NULL; const pal_cg_struct *cg_ptr = NULL; u8 *flw_ptr; flw_ptr = iua_rv_msg.msgcontent.isdn_msg.ie_content; len = iua_rv_msg.msg_length - 5; link_id = iua_rv_msg.e1_no; if((circuit_ptr = pal_isdn_find_circuit_of_link(link_id)) == NULL) { isdn_log_err(0, "m_mdsc: link_id %d is unknown link!\r\n", link_id); monitor_isdn_msg(0, "RV=>", &iua_rv_msg,COL_YELLOW); return ISDN_CM_FAILED; } cg_id = circuit_ptr->cg_id; cg_ptr = pal_cg_ptr(cg_id); if(cg_ptr == NULL) return ISDN_CM_FAILED; if(cg_ptr->attrib.protocol != PROTO_ISDN) return ISDN_CM_FAILED; if(!(cg_ptr->attrib.variant == VARIANT_ITU || cg_ptr->attrib.variant == VARIANT_ANSI || cg_ptr->attrib.variant == VARIANT_QSIG) || (cg_ptr->attrib.variant == VARIANT_QSIG && (cg_ptr->attrib.nfas.flag || circuit_ptr->attrib.user_network_if == NETWORK_SIDE))) return ISDN_CM_FAILED; if(cg_ptr->attrib.variant != VARIANT_ANSI) { isdn_log_err(0, "variant type=%d, is not ansi!\r\n", cg_ptr->attrib.variant); monitor_isdn_msg(0, "RV=>", &iua_rv_msg, COL_YELLOW); return ISDN_CM_FAILED; } if(iua_rv_msg.msgcontent.isdn_msg.msg_m.cr_len != 2) { isdn_log_err(0, "call reference len is not 2!)\n"); //dummy call reference return ISDN_CM_FAILED; } cref = iua_rv_msg.msgcontent.isdn_msg.msg_m.call_ref[0]; cref = (cref << 8) | (iua_rv_msg.msgcontent.isdn_msg.msg_m.call_ref[1]); msg_type = iua_rv_msg.msgcontent.isdn_msg.msg_m.msg_type; memset(&isdn_sd_msg, 0, sizeof(IsdnMsgStr)); memset(&isdn_rv_msg, 0, sizeof(IsdnMsgStr)); if(cref & 0x7FFF) //NOT Global call reference message { isdn_log_err(pid, "Invalid global call reference, CR=0x%02x\r\n",cref); return ISDN_CM_FAILED; } memcpy(&isdn_rv_msg.msg_m, &iua_rv_msg.msgcontent.isdn_msg.msg_m, sizeof(MsgMan)); ret = maintenance_msg_decode(&isdn_rv_msg, flw_ptr, msg_type, len); if(ret != 1) { isdn_log_err(0, "decode msg err!\r\n"); return ISDN_CM_FAILED; } switch(msg_type) { case MSG_SERVICE: if((cref & 0x8000) != 0) { isdn_log_err(0, "the call reference of service is err!\r\n"); return ISDN_CM_FAILED; } if(cg_ptr->attrib.nfas.flag) { if((isdn_rv_msg.msg_list.service.chnl_id.pres) && (isdn_rv_msg.msg_list.service.chnl_id.b3.int_id_pre)) { if((circuit_newId = find_circuit_by_interfaceId(cg_id, isdn_rv_msg.msg_list.service.chnl_id.b3.int_id)) == -1) { if(circuit_ptr->attrib.plat_id == isdn_rs.attrib.systemID) { monitor_isdn_msg(0, "RV=>", &iua_rv_msg, COL_YELLOW); isdn_redirect_send(&iua_rv_msg, 3); //send to another plat return ISDN_CM_FAILED; } else { isdn_log_err(0, "not find current circuit! circuit id=%d\r\n", circuit_ptr->id); return ISDN_CM_FAILED; } } else { circuit_ptr = pal_circuit_ptr(circuit_newId); if(circuit_ptr == NULL) { isdn_log_err(0, "receive SERVICE err! circuit_id=%d, can't find circuit_ptr!\r\n", circuit_newId); return ISDN_CM_FAILED; } if(circuit_ptr->cg_id != cg_id) return ISDN_CM_FAILED; } } else { isdn_log_err(0, "err!\n"); return ISDN_CM_FAILED; } } if((isdn_rv_msg.msg_list.service.chnl_id.pres) && (isdn_rv_msg.msg_list.service.chnl_id.b3.int_type)) { head_cic = circuit_ptr->attrib.head_cic; if(circuit_ptr->attrib.cic_range == 24) head_cic--; if(isdn_rv_msg.msg_list.service.chnl_id.b3.has_chnl) cic = head_cic + isdn_rv_msg.msg_list.service.chnl_id.b3.chnl_num; else { if(circuit_ptr->attrib.cic_range == 24) // T1 cic = circuit_ptr->attrib.head_cic + 23; else cic = circuit_ptr->attrib.head_cic; } } else { isdn_log_err(0, "SERVICE does not include chnl_id ie(pres=%d), or chnl_id does not include cic(int_type=%d)!\r\n", isdn_rv_msg.msg_list.service.chnl_id.pres, isdn_rv_msg.msg_list.service.chnl_id.b3.int_type); return ISDN_CM_FAILED; } break; case MSG_SERVICE_ACK: if(cg_ptr->attrib.nfas.flag) { if((isdn_rv_msg.msg_list.servAck.chnl_id.pres) && (isdn_rv_msg.msg_list.servAck.chnl_id.b3.int_id_pre)) { if((circuit_newId = find_circuit_by_interfaceId(cg_id, isdn_rv_msg.msg_list.servAck.chnl_id.b3.int_id)) == -1) { if(circuit_ptr->attrib.plat_id == isdn_rs.attrib.systemID) { monitor_isdn_msg(0, "RV=>", &iua_rv_msg, COL_YELLOW); isdn_redirect_send(&iua_rv_msg, 3); //send to another plat return ISDN_CM_FAILED; } else { isdn_log_err(0, "not find current circuit! circuit id=%d\r\n", circuit_ptr->id); return ISDN_CM_FAILED; } } else { circuit_ptr = pal_circuit_ptr(circuit_newId); if(circuit_ptr == NULL) { isdn_log_err(0, "receive SERVICE ACK err! circuit_id=%d, can't find circuit_ptr!\r\n", circuit_newId); return ISDN_CM_FAILED; } if(circuit_ptr->cg_id != cg_id) return ISDN_CM_FAILED; } } else { isdn_log_err(0, "err!\n"); return ISDN_CM_FAILED; } } if((isdn_rv_msg.msg_list.servAck.chnl_id.pres) && (isdn_rv_msg.msg_list.servAck.chnl_id.b3.int_type)) { head_cic = circuit_ptr->attrib.head_cic; if(circuit_ptr->attrib.cic_range == 24) head_cic--; if(isdn_rv_msg.msg_list.servAck.chnl_id.b3.has_chnl) cic = head_cic + isdn_rv_msg.msg_list.servAck.chnl_id.b3.chnl_num; else { if(circuit_ptr->attrib.cic_range == 24) // T1 cic = circuit_ptr->attrib.head_cic + 23; else cic = circuit_ptr->attrib.head_cic; } } else { isdn_log_err(0, "SERVICE ACK does not include chnl_id ie(pres=%d), or chnl_id does not include cic(int_type=%d)!\r\n", isdn_rv_msg.msg_list.servAck.chnl_id.pres, isdn_rv_msg.msg_list.servAck.chnl_id.b3.int_type); return ISDN_CM_FAILED; } break; default: return ISDN_CM_FAILED; } head_cic = circuit_ptr->attrib.head_cic; if(circuit_ptr->attrib.cic_range == 24) head_cic--; if((cic < circuit_ptr->attrib.head_cic) || (cic - circuit_ptr->attrib.head_cic) >= (circuit_ptr->attrib.cic_range)) { isdn_log_err(0, "decode cic err!cic=0x04x\r\n", cic); return ISDN_CM_FAILED; } else { pid = find_port_by_cic(cic, circuit_ptr->id); if((circuit_ptr->attrib.d_chnl+head_cic) == cic) isdn_rs.port_pond[pid].timer_flag |= DC_M_FLAG; else isdn_rs.port_pond[pid].timer_flag |= BC_M_FLAG; } monitor_isdn_msg(pid, "RV=>", &iua_rv_msg, COL_YELLOW); isdn_rs.port_pond[pid].msg_cmd = msg_type; if(isdn_rs.port_pond[pid].timer_flag & DC_M_FLAG) service_dc_proc(pid); else if(isdn_rs.port_pond[pid].timer_flag & BC_M_FLAG) service_bc_proc(pid); if(isdn_rs.port_pond[pid].msg_cmd != 0) { isdn_log_err(pid, "ignore the message! msg_cmd=%d\r\n", isdn_rs.port_pond[pid].msg_cmd); isdn_rs.port_pond[pid].msg_cmd = 0; } return ISDN_CM_OK; } /************************************************************* Function: isdn_receive_msg Description: isdn receive msg from iua Input: NULL Return: ISDN_CM_OK:success ISDN_CM_FAILED:failed *************************************************************/ int isdn_receive_msg() { u16 len; int link_id; xua_up_msg_t *src = 0; if((get_xua_msg(IUA_APP, &src)) <= 0) { // printf("isdn get iua err!\n"); return ISDN_CM_FAILED; } memcpy(&iua_rv_msg.msg_class, src, sizeof(xua_up_msg_t)); link_id = iua_rv_msg.e1_no; if(iua_rv_msg.msg_class == IUA_MGMT_CMD) //heartbeat { if(iua_rv_msg.msgcontent.lkmsg.opercode == M2UA_LK_DOWN) { isdn_rs.link_pond[link_id].lk2_status = LK_OOS; //out of service } else if(iua_rv_msg.msgcontent.lkmsg.opercode == M2UA_LK_UP) { isdn_rs.link_pond[link_id].lk2_status = LK_IS; //in service isdn_rs.link_pond[link_id].link_heartbeat_time = 0; } isdn_rs.link_pond[link_id].lk3_status = isdn_rs.link_pond[link_id].lk2_status; return ISDN_CM_FAILED; } len = ntohs(iua_rv_msg.msg_length); iua_rv_msg.msg_length = len; if((iua_rv_msg.msgcontent.isdn_msg.msg_m.proto_Discr == PROTOCOL_DISCR) && (len > 4)) { isdn_mdsc_proc(); return ISDN_CM_OK; } else if((iua_rv_msg.msgcontent.isdn_msg.msg_m.proto_Discr == M_PROTOCOL_DISCR) && (len > 4)) { isdn_m_mdsc_proc(); return ISDN_CM_OK; } isdn_log_err(0, "there is not isdn msg!\r\n"); return ISDN_CM_FAILED; } int isdn_redirect_receive() { int type, link_id; message_list msg_trans; xua_up_msg_t iua_msg; if(iptrGetMessage(&msg_trans, ISDN_IP_PORT) == 0) { // isdn_log_err(0, "do not receive msg from another plat!\r\n"); return ISDN_CM_FAILED; } if(msg_trans.msgSrcIP != isdn_rs.attrib.isdn_remote_ip) { isdn_log_err(0, "remote ip is not compatible!\r\n"); return ISDN_CM_FAILED; } type = msg_trans.msgContent[0]; switch(type) { case 1: //heartbeat if(msg_trans.msgLength == 3) { link_id = msg_trans.msgContent[1]; isdn_rs.link_pond[link_id].dc_status = msg_trans.msgContent[2]; isdn_rs.link_pond[link_id].plat_heartbeat_time = isdn_timer_var.t1s; return ISDN_CM_OK; } break; case 2: //msg, don't decode msg, and send the msg to the other switch if(msg_trans.msgLength > 5) { memcpy(&iua_msg, msg_trans.msgContent+1, msg_trans.msgLength-1); put_xua_msg(&iua_msg); return ISDN_CM_OK; } break; case 3: //msg, need decode msg if(msg_trans.msgLength > 5) { memcpy(&iua_rv_msg.msg_class, msg_trans.msgContent+1, msg_trans.msgLength-1); iua_rv_msg.msg_length = ntohs(iua_rv_msg.msg_length); if(iua_rv_msg.msgcontent.isdn_msg.msg_m.proto_Discr == PROTOCOL_DISCR) { isdn_mdsc_proc(); return ISDN_CM_OK; } else if(iua_rv_msg.msgcontent.isdn_msg.msg_m.proto_Discr == M_PROTOCOL_DISCR) { isdn_m_mdsc_proc(); return ISDN_CM_OK; } } break; default: break; } isdn_log_err(0, "redirect receive err!\n"); return ISDN_CM_FAILED; }