Files
svc.ems/plat/isdn/src/isdn_msg.c
2024-09-27 15:39:34 +08:00

3440 lines
85 KiB
C

/***********************************************************
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:
<author> <date> <version> <desc>
************************************************************/
#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;
}