提交 9bcabce6 authored 作者: Stefan Knoblich's avatar Stefan Knoblich

Add initial Basic Rate Interface (BRI) support...

Short summary of changes:
    (Massive) rework of the Q.921 layer
    Q.931 changes to get BRI PTMP working and cleanups (more to come...)
    Add Hi-Layer compat and Progress IE to outgoing SETUP messages
    Improve handling of call tear-down in zap_isdn.c
    Open ZAP I/O channels after processing the dialplan for incoming calls
    Bearer Capability and Channel ID IE handling improved for BRI/PRI and A-law/u-law

    ...and a lot of other small changes



git-svn-id: http://svn.openzap.org/svn/openzap/trunk@512 a93c3328-9c30-0410-af19-c9cd2b2d52af
上级 a0d9ff1e
*.o
*.lo
*.so
*.a
*.orig
*.rej
*.log
Makefile
config.*
configure
......@@ -673,6 +673,7 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc
}
static switch_status_t channel_receive_message_b(switch_core_session_t *session, switch_core_session_message_t *msg)
{
switch_channel_t *channel;
......@@ -690,7 +691,7 @@ static switch_status_t channel_receive_message_b(switch_core_session_t *session,
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_PROGRESS);
} else {
zap_set_state_locked(tech_pvt->zchan, ZAP_CHANNEL_STATE_PROGRESS);
zap_set_state_locked_wait(tech_pvt->zchan, ZAP_CHANNEL_STATE_PROGRESS);
}
}
break;
......@@ -700,7 +701,7 @@ static switch_status_t channel_receive_message_b(switch_core_session_t *session,
zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_PROGRESS);
zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_MEDIA);
} else {
zap_set_state_locked(tech_pvt->zchan, ZAP_CHANNEL_STATE_PROGRESS_MEDIA);
zap_set_state_locked_wait(tech_pvt->zchan, ZAP_CHANNEL_STATE_PROGRESS_MEDIA);
}
}
break;
......@@ -709,7 +710,7 @@ static switch_status_t channel_receive_message_b(switch_core_session_t *session,
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_ANSWERED);
} else {
zap_set_state_locked(tech_pvt->zchan, ZAP_CHANNEL_STATE_UP);
zap_set_state_locked_wait(tech_pvt->zchan, ZAP_CHANNEL_STATE_UP);
}
}
break;
......
......@@ -134,8 +134,8 @@
#include "libteletone.h"
#include "zap_buffer.h"
#include "zap_threadmutex.h"
#include "Q931.h"
#include "Q921.h"
#include "Q931.h"
#define XX if (0)
......@@ -232,6 +232,19 @@
else zap_log(ZAP_LOG_WARNING, "VETO Changing state on %d:%d from %s to %s\n", obj->span_id, obj->chan_id, zap_channel_state2str(st), zap_channel_state2str(s)); \
}
#define zap_set_state_locked_wait(obj, s) \
do { \
int __safety = 100; \
zap_set_state_locked(obj, s); \
while(__safety-- && zap_test_flag(obj, ZAP_CHANNEL_STATE_CHANGE)) { \
zap_sleep(10); \
} \
if(!__safety) { \
zap_log(ZAP_LOG_CRIT, "State change not completed\n"); \
} \
} while(0);
typedef enum {
ZAP_STATE_CHANGE_FAIL,
ZAP_STATE_CHANGE_SUCCESS,
......
......@@ -53,10 +53,11 @@ struct zap_isdn_data {
struct zap_sigmsg sigmsg;
zio_signal_cb_t sig_cb;
uint32_t flags;
int32_t mode;
zap_isdn_opts_t opts;
zap_caller_data_t *outbound_crv[32768];
zap_channel_t *channels_local_crv[32768];
zap_channel_t *channels_remote_crv[32768];
zap_isdn_opts_t opts;
};
......
......@@ -117,11 +117,12 @@ typedef enum {
ZAP_TRUNK_T1,
ZAP_TRUNK_J1,
ZAP_TRUNK_BRI,
ZAP_TRUNK_BRI_PTMP,
ZAP_TRUNK_FXO,
ZAP_TRUNK_FXS,
ZAP_TRUNK_NONE
} zap_trunk_type_t;
#define TRUNK_STRINGS "E1", "T1", "J1", "BRI", "FXO", "FXS", "NONE"
#define TRUNK_STRINGS "E1", "T1", "J1", "BRI", "BRI_PTMP", "FXO", "FXS", "NONE"
ZAP_STR2ENUM_P(zap_str2zap_trunk_type, zap_trunk_type2str, zap_trunk_type_t)
typedef enum {
......
......@@ -240,7 +240,7 @@ L3INT ATT5ESSProc0x0fTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom)
if(iFrom == 4)
{
/* TODO Add proc here*/
ret = Q931Tx32(pTrunk,buf,pMes->Size);
ret = Q931Tx32Data(pTrunk,0,buf,pMes->Size);
}
else if (iFrom ==2)
{
......@@ -283,7 +283,7 @@ L3INT ATT5ESSProc0x07TE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom)
if(iFrom == 4)
{
/* TODO Add proc here*/
ret = Q931Tx32(pTrunk,buf,pMes->Size);
ret = Q931Tx32Data(pTrunk,0,buf,pMes->Size);
}
else if (iFrom ==2)
{
......
......@@ -158,12 +158,7 @@ L3INT ATT5ESSPmes_Setup(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT I
L3INT Octet = 0;
/* Q931 Message Header */
OBuf[Octet++] = pMes->ProtDisc; /* Protocol discriminator */
OBuf[Octet++] = 2; /* length is 2 octets */
OBuf[Octet++] = (L3UCHAR)(pMes->CRV>>8) | (pMes->CRVFlag << 7); /* msb */
OBuf[Octet++] = (L3UCHAR)(pMes->CRV); /* lsb */
OBuf[Octet++] = pMes->MesType; /* message header */
Q931MesgHeader(pTrunk, pMes, OBuf, *OSize, &Octet);
/* Sending Complete */
if(Q931IsIEPresent(pMes->SendComplete))
......
......@@ -237,7 +237,7 @@ L3INT DMSProc0x0fTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom)
if(iFrom == 4)
{
/* TODO Add proc here*/
ret = Q931Tx32(pTrunk,buf,pMes->Size);
ret = Q931Tx32Data(pTrunk,0,buf,pMes->Size);
}
else if (iFrom ==2)
{
......@@ -279,7 +279,7 @@ L3INT DMSProc0x07TE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom)
if(iFrom == 4)
{
/* TODO Add proc here*/
ret = Q931Tx32(pTrunk,buf,pMes->Size);
ret = Q931Tx32Data(pTrunk,0,buf,pMes->Size);
}
else if (iFrom ==2)
{
......
......@@ -155,12 +155,7 @@ L3INT DMSPmes_Setup(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize
L3INT Octet = 0;
/* Q931 Message Header */
OBuf[Octet++] = pMes->ProtDisc; /* Protocol discriminator */
OBuf[Octet++] = 2; /* length is 2 octets */
OBuf[Octet++] = (L3UCHAR)(pMes->CRV>>8) | (pMes->CRVFlag << 7); /* msb */
OBuf[Octet++] = (L3UCHAR)(pMes->CRV); /* lsb */
OBuf[Octet++] = pMes->MesType; /* message header */
Q931MesgHeader(pTrunk, pMes, OBuf, *OSize, &Octet);
/* Sending Complete */
if(Q931IsIEPresent(pMes->SendComplete))
......
......@@ -74,8 +74,8 @@ L3INT Q931Api_InitTrunk(Q931_TrunkInfo_t *pTrunk,
Q931Dialect_t Dialect,
Q931NetUser_t NetUser,
Q931_TrunkType_t TrunkType,
Q931TxCB_t Q931Tx34CBProc,
Q931TxCB_t Q931Tx32CBProc,
Q931Tx34CB_t Q931Tx34CBProc,
Q931Tx32CB_t Q931Tx32CBProc,
Q931ErrorCB_t Q931ErrorCBProc,
void *PrivateData32,
void *PrivateData34)
......@@ -97,6 +97,7 @@ L3INT Q931Api_InitTrunk(Q931_TrunkInfo_t *pTrunk,
break;
case Q931_TrType_BRI:
case Q931_TrType_BRI_PTMP:
dchannel = 3;
maxchans = 3;
break;
......@@ -166,6 +167,16 @@ void Q931SetIEProc(L3UCHAR iec, L3UCHAR dialect, q931pie_func_t *Q931PieProc, q9
Q931Uie[dialect][iec] = Q931UieProc;
}
void Q931SetTimeoutProc(L3UCHAR timer, L3UCHAR dialect, q931timeout_func_t *Q931TimeoutProc)
{
if(Q931Timeout != NULL)
Q931Timeout[dialect][timer] = Q931TimeoutProc;
}
void Q931SetTimerDefault(L3UCHAR timer, L3UCHAR dialect, q931timer_t timeout)
{
Q931Timer[dialect][timer] = timeout;
}
L3INT Q931GetMesSize(Q931mes_Generic *pMes)
{
......@@ -212,8 +223,11 @@ static L3INT crv={1};
L3INT Q931GetUniqueCRV(Q931_TrunkInfo_t *pTrunk)
{
L3INT max = (Q931_IS_BRI(pTrunk)) ? Q931_BRI_MAX_CRV : Q931_PRI_MAX_CRV;
crv++;
if (crv > 32766) crv = 1;
crv = (crv <= max) ? crv : 1;
return crv;
}
......@@ -523,7 +537,7 @@ L3INT Q931ReleaseComplete(Q931_TrunkInfo_t *pTrunk, L3UCHAR *buf)
Q931mes_Header *ptr = (Q931mes_Header*)&buf[Q931L4HeaderSpace];
ptr->MesType = Q931mes_RELEASE_COMPLETE;
ptr->CRVFlag = !(ptr->CRVFlag);
return Q931Tx32(pTrunk,buf,ptr->Size);
return Q931Tx32Data(pTrunk,0,buf,ptr->Size);
}
L3INT Q931AckRestart(Q931_TrunkInfo_t *pTrunk, L3UCHAR *buf)
......
......@@ -31,7 +31,7 @@
NOTE: The following are not yet implemented
OnQ921Error Function called every if an error is
deteceted.
detected.
OnQ921Log Function called if logging is active.
......@@ -76,84 +76,149 @@
*****************************************************************************/
/****************************************************************************
* Changes:
*
* - June,July 2008: Stefan Knoblich <s.knoblich@axsentis.de>:
* Add PTMP TEI management
* Add timers
* Add retransmit counters
* Add logging
* Various cleanups
*
****************************************************************************/
#ifndef _Q921
#define _Q921
#define Q921MAXHDLCSPACE 3000
#define L2UCHAR unsigned char /* Min 8 bit */
#define L2INT int /* Min 16 bit signed */
#define L2ULONG unsigned long /* Min 32 bit */
#define L2UCHAR unsigned char /* Min 8 bit */
#define L2USHORT unsigned short /* 16 bit */
#define L2INT int /* Min 16 bit signed */
#define L2ULONG unsigned long /* Min 32 bit */
#define L2TRUNK Q921Data_t *
typedef enum /* Network/User Mode. */
#define Q921_TEI_BCAST 127
#define Q921_TEI_MAX Q921_TEI_BCAST
#define Q921_TEI_DYN_MIN 64
#define Q921_TEI_DYN_MAX 126
typedef enum /* Network/User Mode */
{
Q921_TE=0, /* 0 : User Mode */
Q921_NT=1 /* 1 : Network Mode */
Q921_TE=0, /* 0 : User Mode */
Q921_NT=1 /* 1 : Network Mode */
} Q921NetUser_t;
typedef struct Q921Data Q921Data_t;
typedef int (*Q921TxCB_t) (void *, L2UCHAR *, L2INT);
typedef enum /* Type of connection */
{
Q921_PTP=0, /* 0 : Point-To-Point */
Q921_PTMP=1 /* 1 : Point-To-Multipoint */
} Q921NetType_t;
#define INITIALIZED_MAGIC 42
struct Q921Data
typedef enum
{
Q921_LOG_NONE = 0,
Q921_LOG_ERROR,
Q921_LOG_WARNING,
Q921_LOG_NOTICE,
Q921_LOG_INFO,
Q921_LOG_DEBUG
} Q921LogLevel_t;
/*
* Messages for L2 <-> L3 communication
*/
typedef enum {
Q921_DL_ESTABLISH = 0,
Q921_DL_ESTABLISH_CONFIRM,
Q921_DL_RELEASE,
Q921_DL_RELEASE_CONFIRM,
Q921_DL_DATA,
Q921_DL_UNIT_DATA
} Q921DLMsg_t;
typedef int (*Q921Tx21CB_t) (void *, L2UCHAR *, L2INT);
typedef int (*Q921Tx23CB_t) (void *, Q921DLMsg_t ind, L2UCHAR tei, L2UCHAR *, L2INT);
typedef int (*Q921LogCB_t) (void *, Q921LogLevel_t, char *, L2INT);
struct Q921_Link;
typedef struct Q921Data
{
L2UCHAR HDLCInQueue[Q921MAXHDLCSPACE];
L2INT initialized;
L2UCHAR va;
L2UCHAR vs;
L2UCHAR vr;
L2INT state;
L2UCHAR sapi;
L2UCHAR tei;
L2UCHAR sapi; /*!< User assigned SAPI */
L2UCHAR tei; /*!< User assigned TEI value */
L2INT Q921HeaderSpace;
Q921NetUser_t NetUser;
L2ULONG T200;
L2ULONG T203;
Q921NetType_t NetType;
struct Q921_Link *context; /*!< per-TEI / link context space */
/* timers */
L2ULONG T202; /*!< PTMP TE mode TEI retransmit timer */
L2ULONG T200Timeout;
L2ULONG T201Timeout;
L2ULONG T202Timeout;
L2ULONG T203Timeout;
Q921TxCB_t Q921Tx21Proc;
Q921TxCB_t Q921Tx23Proc;
L2ULONG TM01Timeout;
/* counters */
L2ULONG N200Limit; /*!< max retransmit */
L2ULONG N202; /*!< PTMP TE mode retransmit counter */
L2ULONG N202Limit; /*!< PTMP TE mode max retransmit */
L2ULONG N201Limit; /*!< max number of octets */
L2ULONG k; /*!< max number of unacknowledged I frames */
/* callbacks and callback data pointers */
Q921Tx21CB_t Q921Tx21Proc;
Q921Tx23CB_t Q921Tx23Proc;
void *PrivateData21;
void *PrivateData23;
L2INT Q921HeaderSpace;
};
/* logging */
Q921LogLevel_t loglevel; /*!< trunk loglevel */
Q921LogCB_t Q921LogProc; /*!< log callback procedure */
void *PrivateDataLog; /*!< private data pointer for log proc */
/* tei mgmt */
L2UCHAR tei_map[Q921_TEI_MAX]; /*!< */
L2UCHAR HDLCInQueue[Q921MAXHDLCSPACE]; /*!< HDLC input queue */
} Q921Data_t;
void Q921_InitTrunk(L2TRUNK trunk,
/*
* Public functions
*/
int Q921_InitTrunk(L2TRUNK trunk,
L2UCHAR sapi,
L2UCHAR tei,
Q921NetUser_t NetUser,
Q921NetType_t NetType,
L2INT hsize,
Q921TxCB_t cb21,
Q921TxCB_t cb23,
Q921Tx21CB_t cb21,
Q921Tx23CB_t cb23,
void *priv21,
void *priv23);
int Q921QueueHDLCFrame(L2TRUNK trunk, L2UCHAR *b, L2INT size);
int Q921Rx12(L2TRUNK trunk);
int Q921Rx32(L2TRUNK trunk, L2UCHAR * Mes, L2INT Size);
int Q921Start(L2TRUNK trunk);
int Q921Stop(L2TRUNK trunk);
void Q921SetLogCB(L2TRUNK trunk, Q921LogCB_t func, void *priv);
void Q921SetLogLevel(L2TRUNK trunk, Q921LogLevel_t level);
int Q921Rx12(L2TRUNK trunk);
int Q921Rx32(L2TRUNK trunk, Q921DLMsg_t ind, L2UCHAR tei, L2UCHAR * Mes, L2INT Size);
int Q921QueueHDLCFrame(L2TRUNK trunk, L2UCHAR *b, L2INT size);
void Q921SetGetTimeCB(L2ULONG (*callback)(void));
void Q921TimerTick(L2TRUNK trunk);
int Q921Tx21Proc(L2TRUNK trunk, L2UCHAR *Msg, L2INT size);
int Q921Tx23Proc(L2TRUNK trunk, L2UCHAR *Msg, L2INT size);
extern L2ULONG tLast;
L2ULONG Q921GetTime(void);
void Q921T200TimerStart(L2TRUNK trunk);
void Q921T200TimerStop(L2TRUNK trunk);
void Q921T200TimerReset(L2TRUNK trunk);
void Q921T203TimerStart(L2TRUNK trunk);
void Q921T203TimerStop(L2TRUNK trunk);
void Q921T203TimerReset(L2TRUNK trunk);
void Q921T200TimerExpire(L2TRUNK trunk);
void Q921T203TimerExpire(L2TRUNK trunk);
int Q921SendI(L2TRUNK trunk, L2UCHAR Sapi, char cr, L2UCHAR Tei, char pf, L2UCHAR *mes, L2INT size);
int Q921SendRNR(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf);
int Q921SendREJ(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf);
int Q921SendSABME(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf);
int Q921SendDM(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf);
int Q921SendDISC(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf);
int Q921SendUA(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf);
int Q921ProcSABME(L2TRUNK trunk, L2UCHAR *mes, L2INT size);
#endif
差异被折叠。
......@@ -57,7 +57,7 @@ typedef enum {
/* Single octet information elements */
#define Q931ie_SHIFT 0x90 /* 1001 ---- */
#define Q931ie_MORE_DATA 0xa0 /* 1010 ---- */
#define Q931ie_SENDING_COMPLETE 0xa1 /* 1010 0000 */
#define Q931ie_SENDING_COMPLETE 0xa1 /* 1010 0001 */
#define Q931ie_CONGESTION_LEVEL 0xb0 /* 1011 ---- */
#define Q931ie_REPEAT_INDICATOR 0xd0 /* 1101 ---- */
......@@ -101,6 +101,9 @@ typedef enum {
#define Q931ie_GENERIC_DIGITS 0x37 /* 0011 0111 */
/* Variable Length Information Element to shut up BRI testing */
#define Q931ie_CONNECTED_NUMBER 0x4c /* 0100 1101 */
#define Q931ie_FACILITY 0x1c /* 0001 1101 */
/*****************************************************************************
......@@ -1168,5 +1171,7 @@ L3INT Q931Pie_CongLevel(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf,
L3INT Q931Uie_RevChargeInd(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff);
L3INT Q931Pie_RevChargeInd(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet);
L3INT Q931Uie_Generic(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *pMsg, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *IOff, L3INT *OOff);
L3INT Q931Pie_Generic(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet);
#endif /* _Q931IE_NL */
......@@ -127,6 +127,9 @@ void nationalCreateTE(L3UCHAR i)
Q931SetIEProc(Q931ie_USER_USER, i,Q931Pie_UserUser, Q931Uie_UserUser);
Q931SetIEProc(Q931ie_GENERIC_DIGITS, i,Q931Pie_GenericDigits, Q931Uie_GenericDigits);
Q931SetIEProc(Q931ie_CONNECTED_NUMBER, i, Q931Pie_Generic, Q931Uie_Generic);
Q931SetIEProc(Q931ie_FACILITY, i, Q931Pie_Generic, Q931Uie_Generic);
/* The following define a state machine. The point is that the Message */
/* procs can when search this to find out if the message/state */
/* combination is legale. If not, the proc for unexpected message apply.*/
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论