3440 lines
85 KiB
C
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;
|
|
}
|
|
|