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
This commit is contained in:
Stefan Knoblich 2008-08-22 16:55:01 +00:00
parent 9e4558ab13
commit ff19726bd0
25 changed files with 5149 additions and 1060 deletions

12
libs/freetdm/.gitignore vendored Normal file
View File

@ -0,0 +1,12 @@
*.o
*.lo
*.so
*.a
*.orig
*.rej
*.log
Makefile
config.*
configure

View File

@ -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;

View File

@ -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,

View File

@ -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;
};

View File

@ -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 {

View File

@ -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)
{

View File

@ -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))

View File

@ -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)
{

View File

@ -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))

File diff suppressed because it is too large Load Diff

View File

@ -36,6 +36,7 @@
POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#include "Q921.h"
#include "Q931.h"
#include "national.h"
#include "DMS.h"
@ -67,6 +68,8 @@ q931pmes_func_t *Q931Pmes[Q931MAXDLCT][Q931MAXMES];
q931uie_func_t *Q931Uie[Q931MAXDLCT][Q931MAXIE];
q931pie_func_t *Q931Pie[Q931MAXDLCT][Q931MAXIE];
q931timeout_func_t *Q931Timeout[Q931MAXDLCT][Q931MAXTIMER];
q931timer_t Q931Timer[Q931MAXDLCT][Q931MAXTIMER];
void (*Q931CreateDialectCB[Q931MAXDLCT]) (L3UCHAR iDialect)=
{
@ -250,6 +253,10 @@ void Q931Initialize()
Q931Pie[x][y] = Q931PieDummy;
Q931Uie[x][y] = Q931UieDummy;
}
for(y=0; y < Q931MAXTIMER; y++) {
Q931Timeout[x][y] = Q931TimeoutDummy;
Q931Timer[x][y] = 0;
}
}
if(Q931CreateDialectCB[Q931_Dialect_Q931 + Q931_TE] == NULL)
@ -286,28 +293,38 @@ void Q931Initialize()
}
}
/*****************************************************************************
Function: Q931TimeTick
Description: Called periodically from an external source to allow the
stack to process and maintain it's own timers.
Parameters: ms[IN] Milliseconds since last call.
Return Value: none
*****************************************************************************/
void Q931TimeTick(Q931_TrunkInfo_t *pTrunk, L3ULONG ms)
/**
* Q931TimerTick
* \brief Periodically called to update and check for expired timers
* \param pTrunk Q.931 trunk
*/
void Q931TimerTick(Q931_TrunkInfo_t *pTrunk)
{
(void)pTrunk;
ms=ms; /* avoid warning for now. */
struct Q931_Call *call = NULL;
L3ULONG now = 0;
L3INT x;
/* TODO: Loop through all active calls, check timers and call timout procs
* if timers are expired.
* Implement a function array so each dialect can deal with their own
* timeouts.
*/
/* TODO: Loop through all active calls, check timers and call timout procs
* if timers are expired.
* Implement a function array so each dialect can deal with their own
* timeouts.
*/
now = Q931GetTime();
for(x = 0; x < Q931MAXCALLPERTRUNK; x++) {
call = &pTrunk->call[x];
if(!call->InUse || !call->Timer || !call->TimerID)
continue;
if(call->Timer <= now) {
/* Stop Timer */
Q931StopTimer(pTrunk, x, call->TimerID);
/* Invoke dialect timeout callback */
Q931Timeout[pTrunk->Dialect][call->TimerID](pTrunk, x);
}
}
}
/*****************************************************************************
@ -331,39 +348,65 @@ void Q931TimeTick(Q931_TrunkInfo_t *pTrunk, L3ULONG ms)
see q931errors.h for details.
*****************************************************************************/
L3INT Q931Rx23(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT Size)
L3INT Q931Rx23(Q931_TrunkInfo_t *pTrunk, L3INT ind, L3UCHAR tei, L3UCHAR * buf, L3INT Size)
{
L3UCHAR *Mes = &buf[Q931L2HeaderSpace];
L3INT RetCode = Q931E_NO_ERROR;
Q931mes_Generic *m = (Q931mes_Generic *) pTrunk->L3Buf;
L3INT ISize;
L3UCHAR *Mes = NULL;
L3INT RetCode = Q931E_NO_ERROR;
Q931mes_Generic *m = (Q931mes_Generic *) pTrunk->L3Buf;
L3INT ISize;
L3INT IOff = 0;
L3INT L2HSize = Q931L2HeaderSpace;
L3INT IOff = 0;
switch(ind) {
case Q921_DL_UNIT_DATA: /* DL-UNITDATA indication (UI frame, 3 byte header) */
L2HSize = 3;
/* Reset our decode buffer */
memset(pTrunk->L3Buf, 0, sizeof(pTrunk->L3Buf));
case Q921_DL_DATA: /* DL-DATA indication (I frame, 4 byte header) */
/* Reset our decode buffer */
memset(pTrunk->L3Buf, 0, sizeof(pTrunk->L3Buf));
/* Protocol Discriminator */
m->ProtDisc = Mes[IOff++];
/* L2 Header Offset */
Mes = &buf[L2HSize];
/* CRV */
m->CRVFlag = Mes[IOff + 1] & 0x80;
m->CRV = Q931Uie_CRV(pTrunk, Mes, m->buf, &IOff, &ISize);
/* Protocol Discriminator */
m->ProtDisc = Mes[IOff++];
/* Message Type */
m->MesType = Mes[IOff++];
/* CRV */
m->CRVFlag = (Mes[IOff + 1] >> 7) & 0x01;
m->CRV = Q931Uie_CRV(pTrunk, Mes, m->buf, &IOff, &ISize);
/* Call table proc to unpack codec message */
/*debug */
/* printf("\n\nQ931Rx23- Dialect: %d, MsgType: %d\n",pTrunk->Dialect,m->MesType); */
RetCode = Q931Umes[pTrunk->Dialect][m->MesType](pTrunk, Mes, (Q931mes_Generic *)pTrunk->L3Buf, Q931L4HeaderSpace + IOff , Size - Q931L4HeaderSpace - IOff + 1);
/* Message Type */
m->MesType = Mes[IOff++];
if(RetCode >= Q931E_NO_ERROR)
{
RetCode = Q931Proc[pTrunk->Dialect][m->MesType](pTrunk, pTrunk->L3Buf, 2);
}
/* d'oh a little ugly but this saves us from:
* a) doing Q.921 work in the lower levels (extracting the TEI ourselves)
* b) adding a tei parameter to _all_ Proc functions
*/
if(tei) {
L3INT callIndex = 0;
return RetCode;
/* Find the call using CRV */
RetCode = Q931FindCRV(pTrunk, m->CRV, &callIndex);
if(RetCode == Q931E_NO_ERROR && !pTrunk->call[callIndex].Tei) {
pTrunk->call[callIndex].Tei = tei;
}
}
Q931Log(pTrunk, Q931_LOG_DEBUG, "Received message from Q.921 (ind %d, tei %d, size %d)\nMesType: %d, CRVFlag %d (%s), CRV %d (Dialect: %d)\n", ind, tei, Size,
m->MesType, m->CRVFlag, m->CRVFlag ? "Terminator" : "Originator", m->CRV, pTrunk->Dialect);
RetCode = Q931Umes[pTrunk->Dialect][m->MesType](pTrunk, Mes, (Q931mes_Generic *)pTrunk->L3Buf, IOff, Size - L2HSize);
if(RetCode >= Q931E_NO_ERROR)
{
RetCode = Q931Proc[pTrunk->Dialect][m->MesType](pTrunk, pTrunk->L3Buf, 2);
}
break;
default:
break;
}
return RetCode;
}
/*****************************************************************************
@ -381,6 +424,8 @@ L3INT Q931Rx23(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT Size)
*****************************************************************************/
L3INT Q931Tx34(Q931_TrunkInfo_t *pTrunk, L3UCHAR * Mes, L3INT Size)
{
Q931Log(pTrunk, Q931_LOG_DEBUG, "Sending message to Layer4 (size: %d)\n", Size);
if (pTrunk->Q931Tx34CBProc) {
return pTrunk->Q931Tx34CBProc(pTrunk->PrivateData34, Mes, Size);
}
@ -406,7 +451,11 @@ L3INT Q931Rx43(Q931_TrunkInfo_t *pTrunk,L3UCHAR * buf, L3INT Size)
Q931mes_Header *ptr = (Q931mes_Header*)&buf[Q931L4HeaderSpace];
L3INT RetCode = Q931E_NO_ERROR;
RetCode=Q931Proc[pTrunk->Dialect][ptr->MesType](pTrunk,buf,4);
Q931Log(pTrunk, Q931_LOG_DEBUG, "Receiving message from Layer4 (size: %d, type: %d)\n", Size, ptr->MesType);
RetCode = Q931Proc[pTrunk->Dialect][ptr->MesType](pTrunk, buf, 4);
Q931Log(pTrunk, Q931_LOG_DEBUG, "Q931Rx43 return code: %d\n", RetCode);
return RetCode;
}
@ -428,25 +477,42 @@ L3INT Q931Rx43(Q931_TrunkInfo_t *pTrunk,L3UCHAR * buf, L3INT Size)
see q931errors.h for details.
*****************************************************************************/
L3INT Q931Tx32(Q931_TrunkInfo_t *pTrunk, L3UCHAR * Mes, L3INT Size)
L3INT Q931Tx32Data(Q931_TrunkInfo_t *pTrunk, L3UCHAR bcast, L3UCHAR * Mes, L3INT Size)
{
L3INT OSize;
Q931mes_Generic *ptr = (Q931mes_Generic*)Mes;
L3INT RetCode = Q931E_NO_ERROR;
L3INT iDialect = pTrunk->Dialect;
Q931mes_Generic *ptr = (Q931mes_Generic*)Mes;
L3INT RetCode = Q931E_NO_ERROR;
L3INT iDialect = pTrunk->Dialect;
L3INT Offset = bcast ? (Q931L2HeaderSpace - 1) : Q931L2HeaderSpace;
L3INT OSize;
/* Call pack function through table. */
RetCode = Q931Pmes[iDialect][ptr->MesType](pTrunk, (Q931mes_Generic *)Mes, Size, &pTrunk->L2Buf[Q931L2HeaderSpace], &OSize);
if(RetCode >= Q931E_NO_ERROR)
{
if (pTrunk->Q931Tx32CBProc) {
RetCode = pTrunk->Q931Tx32CBProc(pTrunk->PrivateData32, pTrunk->L2Buf, OSize + Q931L2HeaderSpace);
} else {
RetCode = Q931E_MISSING_CB;
}
}
Q931Log(pTrunk, Q931_LOG_DEBUG, "Sending message to Q.921 (size: %d)\n", Size);
return RetCode;
memset(pTrunk->L2Buf, 0, sizeof(pTrunk->L2Buf));
/* Call pack function through table. */
RetCode = Q931Pmes[iDialect][ptr->MesType](pTrunk, (Q931mes_Generic *)Mes, Size, &pTrunk->L2Buf[Offset], &OSize);
if(RetCode >= Q931E_NO_ERROR)
{
L3INT callIndex;
L3UCHAR tei = 0;
if(ptr->CRV) {
/* Find the call using CRV */
RetCode = Q931FindCRV(pTrunk, ptr->CRV, &callIndex);
if(RetCode != Q931E_NO_ERROR)
return RetCode;
tei = pTrunk->call[callIndex].Tei;
}
if (pTrunk->Q931Tx32CBProc) {
RetCode = pTrunk->Q931Tx32CBProc(pTrunk->PrivateData32, bcast ? Q921_DL_UNIT_DATA : Q921_DL_DATA, tei, pTrunk->L2Buf, OSize + Offset);
} else {
RetCode = Q931E_MISSING_CB;
}
}
return RetCode;
}
@ -575,28 +641,40 @@ L3INT Q931GetCallState(Q931_TrunkInfo_t *pTrunk, L3INT iCRV)
return 0; /* assume state zero for non existing CRV's */
}
/*****************************************************************************
Function: Q931StartTimer
Description: Start a timer.
Parameters: pTrunk Trunk number
callindex call index.
iTimer timer id
*****************************************************************************/
/**
* Q931StartTimer
* \brief Start a timer
* \param pTrunk Q.931 trunk
* \param callindex Index of the call
* \param iTimerID ID of timer
* \return always 0
*/
L3INT Q931StartTimer(Q931_TrunkInfo_t *pTrunk, L3INT callIndex, L3USHORT iTimerID)
{
pTrunk->call[callIndex].Timer = Q931GetTime();
pTrunk->call[callIndex].TimerID = iTimerID;
return 0;
L3ULONG duration = Q931Timer[pTrunk->Dialect][iTimerID];
if(duration) {
pTrunk->call[callIndex].Timer = Q931GetTime() + duration;
pTrunk->call[callIndex].TimerID = iTimerID;
}
return 0;
}
/**
* Q931StopTimer
* \brief Stop a timer
* \param pTrunk Q.931 trunk
* \param callindex Index of the call
* \param iTimerID ID of timer
* \return always 0
*/
L3INT Q931StopTimer(Q931_TrunkInfo_t *pTrunk, L3INT callindex, L3USHORT iTimerID)
{
if(pTrunk->call[callindex].TimerID == iTimerID)
pTrunk->call[callindex].TimerID = 0;
return 0;
if(pTrunk->call[callindex].TimerID == iTimerID)
pTrunk->call[callindex].TimerID = 0;
return 0;
}
L3INT Q931SetState(Q931_TrunkInfo_t *pTrunk, L3INT callIndex, L3INT iState)
@ -609,7 +687,8 @@ L3INT Q931SetState(Q931_TrunkInfo_t *pTrunk, L3INT callIndex, L3INT iState)
L3ULONG Q931GetTime()
{
L3ULONG tNow = 0;
static L3ULONG tLast={0};
static L3ULONG tLast = 0;
if(Q931GetTimeProc != NULL)
{
tNow = Q931GetTimeProc();
@ -758,5 +837,68 @@ const char *q931_error_to_name(q931_error_t error)
}
return q931_error_names[index];
}
/*
* Logging
*/
#include <stdarg.h>
L3INT Q931Log(Q931_TrunkInfo_t *trunk, Q931LogLevel_t level, const char *fmt, ...)
{
char buf[Q931_LOGBUFSIZE];
L3INT len;
va_list ap;
if(!trunk->Q931LogCBProc)
return 0;
if(trunk->loglevel < level)
return 0;
va_start(ap, fmt);
len = vsnprintf(buf, sizeof(buf)-1, fmt, ap);
if(len <= 0) {
/* TODO: error handling */
return -1;
}
if(len >= sizeof(buf))
len = sizeof(buf) - 1;
buf[len] = '\0';
va_end(ap);
return trunk->Q931LogCBProc(trunk->PrivateDataLog, level, buf, len);
}
/**
* Q921SetLogCB
* \brief Set Logging callback function and private data
*/
void Q931SetLogCB(Q931_TrunkInfo_t *trunk, Q931LogCB_t func, void *priv)
{
trunk->Q931LogCBProc = func;
trunk->PrivateDataLog = priv;
}
/**
* Q921SetLogLevel
* \brief Set Loglevel
*/
void Q931SetLogLevel(Q931_TrunkInfo_t *trunk, Q931LogLevel_t level)
{
trunk->loglevel = level;
}
/**
* Q931TimeoutDummy
* \brief Dummy handler for timeouts
* \param pTrunk Q.931 trunk
* \param callIndex Index of call
*/
L3INT Q931TimeoutDummy(Q931_TrunkInfo_t *pTrunk, L3INT callIndex)
{
Q931Log(pTrunk, Q931_LOG_DEBUG, "Timer %d of call %d (CRV: %d) timed out\n", pTrunk->call[callIndex].TimerID, callIndex, pTrunk->call[callIndex].CRV);
return 0;
}

View File

@ -116,11 +116,34 @@ void Q931CreateNT(L3UCHAR i)
Q931SetIEProc(Q931ie_HIGH_LAYER_COMPATIBILITY, i,Q931Pie_HLComp, Q931Uie_HLComp);
Q931SetIEProc(Q931ie_USER_USER, i,Q931Pie_UserUser, Q931Uie_UserUser);
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.*/
/* TODO define state table here */
/* Timer default values */
Q931SetTimerDefault(i, Q931_TIMER_T301, 180000); /* T301: 180s */
Q931SetTimerDefault(i, Q931_TIMER_T302, 15000); /* T302: 15s */
Q931SetTimerDefault(i, Q931_TIMER_T303, 4000); /* T303: 4s */
Q931SetTimerDefault(i, Q931_TIMER_T304, 20000); /* T304: 20s */
Q931SetTimerDefault(i, Q931_TIMER_T305, 30000); /* T305: 30s */
Q931SetTimerDefault(i, Q931_TIMER_T306, 30000); /* T306: 30s */
Q931SetTimerDefault(i, Q931_TIMER_T307, 180000); /* T307: 180s */
Q931SetTimerDefault(i, Q931_TIMER_T308, 4000); /* T308: 4s */
Q931SetTimerDefault(i, Q931_TIMER_T309, 60000); /* T309: 60s */
Q931SetTimerDefault(i, Q931_TIMER_T310, 10000); /* T310: 10s */
Q931SetTimerDefault(i, Q931_TIMER_T312, 12000); /* T312: 12s */
Q931SetTimerDefault(i, Q931_TIMER_T314, 4000); /* T314: 4s */
Q931SetTimerDefault(i, Q931_TIMER_T316, 120000); /* T316: 120s */
Q931SetTimerDefault(i, Q931_TIMER_T317, 90000); /* T317: 90s */
Q931SetTimerDefault(i, Q931_TIMER_T320, 30000); /* T320: 30s */
Q931SetTimerDefault(i, Q931_TIMER_T321, 30000); /* T321: 30s */
Q931SetTimerDefault(i, Q931_TIMER_T322, 4000); /* T322: 4s */
}
/*****************************************************************************
@ -143,7 +166,7 @@ L3INT Q931ProcAlertingNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom)
Q931StartTimer(pTrunk, callIndex, 303);
if(iFrom == 4)
{
ret = Q931Tx32(pTrunk,buf,pMes->Size);
ret = Q931Tx32Data(pTrunk,0,buf,pMes->Size);
}
else if (iFrom ==2)
{
@ -175,7 +198,7 @@ L3INT Q931ProcCallProceedingNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iF
if(iFrom == 4)
{
/* TODO Add proc here*/
ret = Q931Tx32(pTrunk,buf,pMes->Size);
ret = Q931Tx32Data(pTrunk,0,buf,pMes->Size);
}
else if (iFrom ==2)
{
@ -208,7 +231,7 @@ L3INT Q931ProcConnectNT(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)
{
@ -241,7 +264,7 @@ L3INT Q931ProcConnectAckNT(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)
{
@ -274,7 +297,7 @@ L3INT Q931ProcProgressNT(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)
{
@ -313,7 +336,10 @@ L3INT Q931ProcSetupNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom)
return ret;
pMes->CRV = pTrunk->call[callIndex].CRV;
ret = Q931Tx32(pTrunk,buf,pMes->Size);
/*
* Outgoing SETUP message will be broadcasted in PTMP mode
*/
ret = Q931Tx32Data(pTrunk, Q931_IS_PTP(pTrunk) ? 0 : 1, buf, pMes->Size);
if(ret)
return ret;
@ -389,7 +415,7 @@ L3INT Q931ProcSetupAckNT(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)
{
@ -422,7 +448,7 @@ L3INT Q931ProcResumeNT(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)
{
@ -455,7 +481,7 @@ L3INT Q931ProcResumeAckNT(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)
{
@ -488,7 +514,7 @@ L3INT Q931ProcResumeRejectNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFro
if(iFrom == 4)
{
/* TODO Add proc here*/
ret = Q931Tx32(pTrunk,buf,pMes->Size);
ret = Q931Tx32Data(pTrunk,0,buf,pMes->Size);
}
else if (iFrom ==2)
{
@ -521,7 +547,7 @@ L3INT Q931ProcSuspendNT(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)
{
@ -554,7 +580,7 @@ L3INT Q931ProcSuspendAckNT(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)
{
@ -587,7 +613,7 @@ L3INT Q931ProcSuspendRejectNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFr
if(iFrom == 4)
{
/* TODO Add proc here*/
ret = Q931Tx32(pTrunk,buf,pMes->Size);
ret = Q931Tx32Data(pTrunk,0,buf,pMes->Size);
}
else if (iFrom ==2)
{
@ -620,7 +646,7 @@ L3INT Q931ProcUserInformationNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT i
if(iFrom == 4)
{
/* TODO Add proc here*/
ret = Q931Tx32(pTrunk,buf,pMes->Size);
ret = Q931Tx32Data(pTrunk,0,buf,pMes->Size);
}
else if (iFrom ==2)
{
@ -653,7 +679,7 @@ L3INT Q931ProcDisconnectNT(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)
{
@ -686,7 +712,7 @@ L3INT Q931ProcReleaseNT(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)
{
@ -719,7 +745,7 @@ L3INT Q931ProcReleaseCompleteNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT i
if(iFrom == 4)
{
/* TODO Add proc here*/
ret = Q931Tx32(pTrunk,buf,pMes->Size);
ret = Q931Tx32Data(pTrunk,0,buf,pMes->Size);
}
else if (iFrom ==2)
{
@ -752,7 +778,7 @@ L3INT Q931ProcRestartNT(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)
{
@ -785,7 +811,7 @@ L3INT Q931ProcRestartAckNT(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)
{
@ -818,7 +844,7 @@ L3INT Q931ProcCongestionControlNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT
if(iFrom == 4)
{
/* TODO Add proc here*/
ret = Q931Tx32(pTrunk,buf,pMes->Size);
ret = Q931Tx32Data(pTrunk,0,buf,pMes->Size);
}
else if (iFrom ==2)
{
@ -851,7 +877,7 @@ L3INT Q931ProcInformationNT(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)
{
@ -884,7 +910,7 @@ L3INT Q931ProcNotifyNT(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)
{
@ -917,7 +943,7 @@ L3INT Q931ProcStatusNT(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)
{
@ -950,7 +976,7 @@ L3INT Q931ProcStatusEnquiryNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFr
if(iFrom == 4)
{
/* TODO Add proc here*/
ret = Q931Tx32(pTrunk,buf,pMes->Size);
ret = Q931Tx32Data(pTrunk,0,buf,pMes->Size);
}
else if (iFrom ==2)
{
@ -983,7 +1009,7 @@ L3INT Q931ProcSegmentNT(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)
{
@ -1020,7 +1046,7 @@ L3INT Q932ProcFacilityNT(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)
{
@ -1053,7 +1079,7 @@ L3INT Q932ProcHoldNT(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)
{
@ -1086,7 +1112,7 @@ L3INT Q932ProcHoldAckNT(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)
{
@ -1119,7 +1145,7 @@ L3INT Q932ProcHoldRejectNT(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)
{
@ -1152,7 +1178,7 @@ L3INT Q932ProcRegisterNT(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)
{
@ -1185,7 +1211,7 @@ L3INT Q932ProcRetrieveNT(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)
{
@ -1218,7 +1244,7 @@ L3INT Q932ProcRetrieveAckNT(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)
{
@ -1251,7 +1277,7 @@ L3INT Q932ProcRetrieveRejectNT(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iF
if(iFrom == 4)
{
/* TODO Add proc here*/
ret = Q931Tx32(pTrunk,buf,pMes->Size);
ret = Q931Tx32Data(pTrunk,0,buf,pMes->Size);
}
else if (iFrom ==2)
{

View File

@ -123,6 +123,9 @@ void Q931CreateTE(L3UCHAR i)
Q931SetIEProc(Q931ie_HIGH_LAYER_COMPATIBILITY, i,Q931Pie_HLComp, Q931Uie_HLComp);
Q931SetIEProc(Q931ie_USER_USER, i,Q931Pie_UserUser, Q931Uie_UserUser);
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.*/
@ -205,6 +208,24 @@ void Q931CreateTE(L3UCHAR i)
Q931AddStateEntry(i,Q931_U19,
Q931AddStateEntry(i,Q931_U25,
*/
/* Timer default values */
Q931SetTimerDefault(i, Q931_TIMER_T301, 180000); /* T301: 180s */
Q931SetTimerDefault(i, Q931_TIMER_T302, 15000); /* T302: 15s */
Q931SetTimerDefault(i, Q931_TIMER_T303, 4000); /* T303: 4s */
Q931SetTimerDefault(i, Q931_TIMER_T304, 30000); /* T304: 30s */
Q931SetTimerDefault(i, Q931_TIMER_T305, 30000); /* T305: 30s */
Q931SetTimerDefault(i, Q931_TIMER_T308, 4000); /* T308: 4s */
Q931SetTimerDefault(i, Q931_TIMER_T309, 60000); /* T309: 60s */
Q931SetTimerDefault(i, Q931_TIMER_T310, 60000); /* T310: 60s */
Q931SetTimerDefault(i, Q931_TIMER_T313, 4000); /* T313: 4s */
Q931SetTimerDefault(i, Q931_TIMER_T314, 4000); /* T314: 4s */
Q931SetTimerDefault(i, Q931_TIMER_T316, 120000); /* T316: 120s */
Q931SetTimerDefault(i, Q931_TIMER_T317, 90000); /* T317: 90s */
Q931SetTimerDefault(i, Q931_TIMER_T318, 4000); /* T318: 4s */
Q931SetTimerDefault(i, Q931_TIMER_T319, 4000); /* T319: 4s */
Q931SetTimerDefault(i, Q931_TIMER_T321, 30000); /* T321: 30s */
Q931SetTimerDefault(i, Q931_TIMER_T322, 4000); /* T322: 4s */
}
/*****************************************************************************
@ -227,7 +248,7 @@ L3INT Q931ProcAlertingTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom)
Q931StartTimer(pTrunk, callIndex, 303);
if(iFrom == 4)
{
ret = Q931Tx32(pTrunk,buf,pMes->Size);
ret = Q931Tx32Data(pTrunk,0,buf,pMes->Size);
}
else if (iFrom ==2)
{
@ -259,7 +280,7 @@ L3INT Q931ProcCallProceedingTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iF
if(iFrom == 4)
{
/* TODO Add proc here*/
ret = Q931Tx32(pTrunk,buf,pMes->Size);
ret = Q931Tx32Data(pTrunk,0,buf,pMes->Size);
}
else if (iFrom ==2)
{
@ -292,7 +313,7 @@ L3INT Q931ProcConnectTE(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)
{
@ -329,7 +350,7 @@ L3INT Q931ProcConnectAckTE(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)
{
@ -362,7 +383,7 @@ L3INT Q931ProcProgressTE(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)
{
@ -399,7 +420,7 @@ L3INT Q931ProcSetupTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom)
return ret;
pMes->CRV = pTrunk->call[callIndex].CRV;
ret = Q931Tx32(pTrunk,buf,pMes->Size);
ret = Q931Tx32Data(pTrunk,0,buf,pMes->Size);
if(ret)
return ret;
@ -475,7 +496,7 @@ L3INT Q931ProcSetupAckTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom)
Q931StartTimer(pTrunk, callIndex, 303);
if(iFrom == 4)
{
ret = Q931Tx32(pTrunk,buf,pMes->Size);
ret = Q931Tx32Data(pTrunk,0,buf,pMes->Size);
}
else if (iFrom ==2)
{
@ -504,7 +525,7 @@ L3INT Q931ProcResumeTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom)
pMes->CRV = pTrunk->call[callIndex].CRV;
/* Send RESUME to network */
ret=Q931Tx32(pTrunk,buf, pMes->Size);
ret=Q931Tx32Data(pTrunk,0,buf, pMes->Size);
if(ret != Q931E_NO_ERROR)
return ret;
@ -544,7 +565,7 @@ L3INT Q931ProcResumeAckTE(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)
{
@ -577,7 +598,7 @@ L3INT Q931ProcResumeRejectTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFro
if(iFrom == 4)
{
/* TODO Add proc here*/
ret = Q931Tx32(pTrunk,buf,pMes->Size);
ret = Q931Tx32Data(pTrunk,0,buf,pMes->Size);
}
else if (iFrom ==2)
{
@ -610,7 +631,7 @@ L3INT Q931ProcSuspendTE(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)
{
@ -643,7 +664,7 @@ L3INT Q931ProcSuspendAckTE(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)
{
@ -676,7 +697,7 @@ L3INT Q931ProcSuspendRejectTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFr
if(iFrom == 4)
{
/* TODO Add proc here*/
ret = Q931Tx32(pTrunk,buf,pMes->Size);
ret = Q931Tx32Data(pTrunk,0,buf,pMes->Size);
}
else if (iFrom ==2)
{
@ -709,7 +730,7 @@ L3INT Q931ProcUserInformationTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT i
if(iFrom == 4)
{
/* TODO Add proc here*/
ret = Q931Tx32(pTrunk,buf,pMes->Size);
ret = Q931Tx32Data(pTrunk,0,buf,pMes->Size);
}
else if (iFrom ==2)
{
@ -730,6 +751,9 @@ L3INT Q931ProcDisconnectTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom)
L3INT ret=Q931E_NO_ERROR;
Q931mes_Header *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace];
Q931Log(pTrunk, Q931_LOG_DEBUG, "Processing DISCONNECT message from %s for CRV: %d (%#hx)\n",
iFrom == 4 ? "Local" : "Remote", pMes->CRV, pMes->CRV);
/* Find the call using CRV */
ret = Q931FindCRV(pTrunk, pMes->CRV, &callIndex);
if(ret != Q931E_NO_ERROR)
@ -742,7 +766,7 @@ L3INT Q931ProcDisconnectTE(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)
{
@ -765,7 +789,7 @@ L3INT Q931ProcReleaseTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFrom)
L3INT ret = Q931E_NO_ERROR;
if(iFrom == 4) {
/* TODO Add proc here*/
ret = Q931Tx32(pTrunk,buf,pMes->Size);
ret = Q931Tx32Data(pTrunk,0,buf,pMes->Size);
} else if(state == Q931_U0 && iFrom == 2) {
Q931Tx34(pTrunk,buf,pMes->Size);
ret = Q931ReleaseComplete(pTrunk, buf);
@ -805,6 +829,9 @@ L3INT Q931ProcReleaseCompleteTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT i
if(ret != Q931E_NO_ERROR)
return ret;
pTrunk->call[callIndex].InUse = 0;
/* TODO: experimental, send RELEASE_COMPLETE message */
ret = Q931Tx32Data(pTrunk,0,buf,pMes->Size);
}
}
@ -838,7 +865,7 @@ L3INT Q931ProcRestartTE(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)
{
@ -877,7 +904,7 @@ L3INT Q931ProcRestartAckTE(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)
{
@ -910,7 +937,7 @@ L3INT Q931ProcCongestionControlTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT
if(iFrom == 4)
{
/* TODO Add proc here*/
ret = Q931Tx32(pTrunk,buf,pMes->Size);
ret = Q931Tx32Data(pTrunk,0,buf,pMes->Size);
}
else if (iFrom ==2)
{
@ -943,7 +970,7 @@ L3INT Q931ProcInformationTE(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)
{
@ -976,7 +1003,7 @@ L3INT Q931ProcNotifyTE(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)
{
@ -1009,7 +1036,7 @@ L3INT Q931ProcStatusTE(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)
{
@ -1042,7 +1069,7 @@ L3INT Q931ProcStatusEnquiryTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iFr
if(iFrom == 4)
{
/* TODO Add proc here*/
ret = Q931Tx32(pTrunk,buf,pMes->Size);
ret = Q931Tx32Data(pTrunk,0,buf,pMes->Size);
}
else if (iFrom ==2)
{
@ -1075,7 +1102,7 @@ L3INT Q931ProcSegmentTE(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)
{
@ -1112,7 +1139,7 @@ L3INT Q932ProcFacilityTE(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)
{
@ -1145,7 +1172,7 @@ L3INT Q932ProcHoldTE(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)
{
@ -1178,7 +1205,7 @@ L3INT Q932ProcHoldAckTE(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)
{
@ -1211,7 +1238,7 @@ L3INT Q932ProcHoldRejectTE(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)
{
@ -1244,7 +1271,7 @@ L3INT Q932ProcRegisterTE(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)
{
@ -1277,7 +1304,7 @@ L3INT Q932ProcRetrieveTE(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)
{
@ -1310,7 +1337,7 @@ L3INT Q932ProcRetrieveAckTE(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)
{
@ -1343,7 +1370,7 @@ L3INT Q932ProcRetrieveRejectTE(Q931_TrunkInfo_t *pTrunk, L3UCHAR * buf, L3INT iF
if(iFrom == 4)
{
/* TODO Add proc here*/
ret = Q931Tx32(pTrunk,buf,pMes->Size);
ret = Q931Tx32Data(pTrunk,0,buf,pMes->Size);
}
else if (iFrom ==2)
{

View File

@ -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)

View File

@ -318,73 +318,74 @@ L3INT Q931Pie_BearerCap(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf,
L3INT Beg=*Octet;/* remember current offset */
L3INT li;
Q931Log(pTrunk, Q931_LOG_DEBUG, "Encoding Bearer Capability IE\n");
OBuf[(*Octet)++] = Q931ie_BEARER_CAPABILITY ;
li=(*Octet)++; /* remember length position */
/* Octet 3 - Coding standard / Information transfer capability */
OBuf[(*Octet)++] = 0x80 | (pIE->CodStand<<5) | (pIE->ITC & 0x1f);
OBuf[(*Octet)++] = 0x80 | ((pIE->CodStand << 5) & 0x60) | (pIE->ITC & 0x1f);
/* Octet 4 - Transfer mode / Information transfer rate */
OBuf[(*Octet)++] = 0x80 | (pIE->TransMode<<5) | (pIE->ITR & 0x1f);
OBuf[(*Octet)++] = 0x80 | ((pIE->TransMode << 5) & 0x60) | (pIE->ITR & 0x1f);
if(pIE->ITR == 0x18)
{
/* Octet 4.1 - Rate Multiplier */
OBuf[(*Octet)++] = 0x80 | pIE->RateMul;
OBuf[(*Octet)++] = 0x80 | (pIE->RateMul & 0x7f);
}
/* Octet 5 - Layer 1 Ident / User information layer 1 protocol*/
/* Octet 5 - Layer 1 Ident / User information layer 1 protocol */
if(pIE->Layer1Ident == 0x01)
{
if(((pIE->ITC == 0x08) && (pIE->UIL1Prot == 0x01 || pIE->UIL1Prot == 0x08))
|| ((pIE->ITC == 0x10) && (pIE->UIL1Prot == 0x02 || pIE->UIL1Prot == 0x03)))
if(((pIE->ITC == 0x08) && (pIE->UIL1Prot == 0x01 || pIE->UIL1Prot == 0x08)) ||
((pIE->ITC == 0x10) && (pIE->UIL1Prot == 0x02 || pIE->UIL1Prot == 0x03)))
{
OBuf[(*Octet)++] = 0x00 | (pIE->Layer1Ident<<5) | (pIE->UIL1Prot & 0x15);
OBuf[(*Octet)++] = 0x00 | ((pIE->Layer1Ident << 5) & 0x60) | (pIE->UIL1Prot & 0x15);
/* Octet 5a - SyncAsync/Negot/UserRate */
OBuf[(*Octet)++] = 0x00 | (pIE->SyncAsync<<6) | (pIE->Negot<<5) | (pIE->UserRate&0x1f);
OBuf[(*Octet)++] = 0x00 | ((pIE->SyncAsync << 6) & 0x40) | ((pIE->Negot << 5) & 0x20) | (pIE->UserRate & 0x1f);
/* Octet 5b - one of two types */
if(pIE->UIL1Prot == 0x01) /* ITU V.110, I.460 and X.30 */
{
/* Octet 5b - Intermed rate/ Nic on Tx/Nix on Rx/FlowCtlTx/FlowCtlRx */
OBuf[(*Octet)++] = 0x00
| (pIE->InterRate<<6)
| (pIE->NIConTx << 4)
| (pIE->NIConRx << 3)
| (pIE->FlowCtlTx << 2)
| (pIE->FlowCtlRx << 1);
| ((pIE->InterRate << 6) & 0x60)
| ((pIE->NIConTx << 4) & 0x10)
| ((pIE->NIConRx << 3) & 0x08)
| ((pIE->FlowCtlTx << 2) & 0x04)
| ((pIE->FlowCtlRx << 1) & 0x02);
}
else if(pIE->UIL1Prot == 0x08) /* ITU V.120 */
{
/* Octet 5b - HDR/Multiframe/Mode/LLINegot/Assignor/Inbandneg*/
OBuf[(*Octet)++] = 0x00
| (pIE->InterRate << 6)
| (pIE->MultiFrame << 5)
| (pIE->Mode << 4)
| (pIE->LLInegot << 3)
| (pIE->Assignor << 2)
| (pIE->InBandNeg << 1);
| ((pIE->InterRate << 6) & 0x60)
| ((pIE->MultiFrame << 5) & 0x20)
| ((pIE->Mode << 4) & 0x10)
| ((pIE->LLInegot << 3) & 0x08)
| ((pIE->Assignor << 2) & 0x04)
| ((pIE->InBandNeg << 1) & 0x02);
}
/* Octet 5c - NumStopBits/NumStartBits/Parity */
OBuf[(*Octet)++] = 0x00
| (pIE->NumStopBits << 5 )
| (pIE->NumDataBits << 3 )
| (pIE->Parity);
| ((pIE->NumStopBits << 5) & 0x60)
| ((pIE->NumDataBits << 3) & 0x18)
| (pIE->Parity & 0x07);
/* Octet 5d - Duplex Mode/Modem Type */
OBuf[(*Octet)++] = 0x80 | (pIE->DuplexMode<<6) | (pIE->ModemType);
OBuf[(*Octet)++] = 0x80 | ((pIE->DuplexMode << 6) & 0x40) | (pIE->ModemType & 0x3f);
}
else
{
OBuf[(*Octet)++] = 0x80 | (pIE->Layer1Ident<<5) | (pIE->UIL1Prot & 0x1F);
else {
OBuf[(*Octet)++] = 0x80 | ((pIE->Layer1Ident << 5) & 0x60) | (pIE->UIL1Prot & 0x1f);
}
}
/* Octet 6 - Layer2Ident/User information layer 2 prtocol */
if(pIE->Layer2Ident == 0x02)
{
OBuf[(*Octet)++] = 0x80 | (pIE->Layer2Ident<<5) | (pIE->UIL2Prot);
if(pIE->Layer2Ident == 0x02) {
OBuf[(*Octet)++] = 0x80 | ((pIE->Layer2Ident << 5) & 0x60) | (pIE->UIL2Prot & 0x1f);
}
/* Octet 7 - Layer 3 Ident/ User information layer 3 protocol */
@ -392,17 +393,16 @@ L3INT Q931Pie_BearerCap(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf,
{
if(pIE->UIL3Prot == 0x0c)
{
OBuf[(*Octet)++] = 0x00 | (pIE->Layer3Ident<<5) | (pIE->UIL3Prot);
OBuf[(*Octet)++] = 0x00 | ((pIE->Layer3Ident << 5) & 0x60) | (pIE->UIL3Prot & 0x1f);
/* Octet 7a - Additional information layer 3 msb */
OBuf[(*Octet)++] = 0x00 | (pIE->AL3Info1);
OBuf[(*Octet)++] = 0x00 | (pIE->AL3Info1 & 0x0f);
/* Octet 7b - Additional information layer 3 lsb */
OBuf[(*Octet)++] = 0x80 | (pIE->AL3Info2);
OBuf[(*Octet)++] = 0x80 | (pIE->AL3Info2 & 0x0f);
}
else
{
OBuf[(*Octet)++] = 0x80 | (pIE->Layer3Ident<<5) | (pIE->UIL3Prot);
else {
OBuf[(*Octet)++] = 0x80 | ((pIE->Layer3Ident << 5) & 0x60) | (pIE->UIL3Prot & 0x1f);
}
}
@ -1152,76 +1152,107 @@ L3INT Q931Pie_CongLevel(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf,
*****************************************************************************/
L3INT Q931Uie_ChanID(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR *OBuf, L3INT *IOff, L3INT *OOff)
{
Q931ie_ChanID * pie = (Q931ie_ChanID*)OBuf;
Q931ie_ChanID *pie = (Q931ie_ChanID*)OBuf;
ie *pIE = &pMsg->ChanID;
L3INT Off = 0;
L3INT Octet = 0;
L3INT IESize;
L3INT Off = 0;
L3INT Octet = 0;
L3INT IESize;
//18 04 e1 80 83 01
*pIE=0;
*pIE = 0;
/* Octet 1 */
pie->IEId = IBuf[Octet];
Octet ++;
Q931Log(pTrunk, Q931_LOG_DEBUG, "Decoding ChanID IE\n");
/* Octet 2 */
IESize = IBuf[Octet ++];
/* Octet 1 */
pie->IEId = IBuf[Octet++];
/* Octet 3 */
pie->IntIDPresent = (IBuf[Octet] >> 6) & 0x01;
pie->IntType = (IBuf[Octet] >> 5) & 0x01;
pie->PrefExcl = (IBuf[Octet] >> 3) & 0x01;
pie->DChanInd = (IBuf[Octet] >> 2) & 0x01;
pie->InfoChanSel = IBuf[Octet] & 0x03;
/* Octet 2 */
IESize = IBuf[Octet++];
Off = Q931ReadExt(&IBuf[Octet+Off], Off);
Octet++;
/* Octet 3 */
pie->IntIDPresent = (IBuf[Octet] >> 6) & 0x01;
pie->IntType = (IBuf[Octet] >> 5) & 0x01;
pie->PrefExcl = (IBuf[Octet] >> 3) & 0x01;
pie->DChanInd = (IBuf[Octet] >> 2) & 0x01;
pie->InfoChanSel = IBuf[Octet] & 0x03;
/* Octet 3.1 */
Off = Q931ReadExt(&IBuf[Octet++], Off);
if(pie->IntIDPresent)
{
pie->InterfaceID = IBuf[Octet+Off] & 0x7f;
/* Octet 3.1 */
if(pie->IntIDPresent)
{
pie->InterfaceID = IBuf[Octet+Off] & 0x7f;
/* Temp fix. Interface id can be extended using the extension bit */
/* this will read the octets, but do nothing with them. this is done */
/* because the usage of this field is a little unclear */
/* 30.jan.2001/JVB */
Off = Q931ReadExt(&IBuf[Octet+Off], Off);
Off++;
}
/* Temp fix. Interface id can be extended using the extension bit */
/* this will read the octets, but do nothing with them. this is done */
/* because the usage of this field is a little unclear */
/* 30.jan.2001/JVB */
Off = Q931ReadExt(&IBuf[Octet+Off], Off);
Off++;
}
if (Octet + Off -2 != IESize) {
/* Octet 3.2 */
if(pie->IntType == 1) /* PRI etc */
{
pie->CodStand = (IBuf[Octet + Off] >> 5) & 0x03;
pie->NumMap = (IBuf[Octet + Off] >> 4) & 0x01;
pie->ChanMapType= IBuf[Octet + Off] & 0x0f;
if ((Octet + Off - 2) != IESize) {
/* Octet 3.2 */
if(pie->IntType == 1) /* PRI etc */
{
pie->CodStand = (IBuf[Octet + Off] >> 5) & 0x03;
pie->NumMap = (IBuf[Octet + Off] >> 4) & 0x01;
pie->ChanMapType = IBuf[Octet + Off] & 0x0f;
Off++;
Off ++;
/* Octet 3.3 */
/* Temp fix. Assume B channel. H channels not supported */
pie->ChanSlot = IBuf[Octet+Off] & 0x7f;
/* Octet 3.3 */
/* Temp fix. Assume B channel. H channels not supported */
pie->ChanSlot = IBuf[Octet+Off] & 0x7f;
/* Some dialects don't follow the extension coding properly for this, but this should be safe for all */
if (Octet + Off -1 != IESize) {
if((Octet + Off - 1) != IESize) {
Off = Q931ReadExt(&IBuf[Octet+Off], Off);
}
Off++;
}
}
Off++;
}
}
Q931IESizeTest(Q931E_CHANID);
Q931IESizeTest(Q931E_CHANID);
Q931SetIE(*pIE, *OOff);
Q931SetIE(*pIE, *OOff);
*IOff = (*IOff) + Octet + Off;
*OOff = (*OOff) + sizeof(Q931ie_BearerCap);
pie->Size = sizeof(Q931ie_BearerCap);
*IOff = (*IOff) + Octet + Off;
*OOff = (*OOff) + sizeof(Q931ie_ChanID);
pie->Size = sizeof(Q931ie_ChanID);
return Q931E_NO_ERROR;
if(pTrunk->loglevel == Q931_LOG_DEBUG)
{
const char *iface;
char tmp[100] = "";
if(!pie->IntType) {
switch(pie->InfoChanSel) {
case 0x0:
iface = "None";
break;
case 0x1:
iface = "B1";
break;
case 0x2:
iface = "B2";
break;
default:
iface = "Any Channel";
}
snprintf(tmp, sizeof(tmp)-1, "InfoChanSel: %d (%s)", pie->InfoChanSel, iface);
}
Q931Log(pTrunk, Q931_LOG_DEBUG,
"\n-------------------------- Q.931 Channel ID ------------------------\n"
" Pref/Excl: %s, Interface Type: %s\n"
" %s\n"
"--------------------------------------------------------------------\n\n",
((pie->PrefExcl) ? "Preferred" : "Exclusive"),
((pie->IntType) ? "PRI/Other" : "BRI"),
tmp);
}
return Q931E_NO_ERROR;
}
/*****************************************************************************
@ -1238,24 +1269,24 @@ L3INT Q931Uie_ChanID(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *pMsg, L3UCHAR *
L3INT Q931Pie_ChanID(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet)
{
Q931ie_ChanID * pIE = (Q931ie_ChanID*)IBuf;
L3INT rc=Q931E_NO_ERROR;
L3INT Beg=*Octet;/* remember current offset */
L3INT rc = Q931E_NO_ERROR;
L3INT Beg = *Octet; /* remember current offset */
L3INT li;
OBuf[(*Octet)++] = Q931ie_CHANNEL_IDENTIFICATION;
li=(*Octet)++; /* remember length position */
li = (*Octet)++; /* remember length position */
/* Octet 3 flags & BRI chan # */
OBuf[(*Octet)++] = 0x80
| (pIE->IntIDPresent << 6)
| (pIE->IntType<<5)
| (pIE->PrefExcl<<3)
| pIE->InfoChanSel;
| ((pIE->IntIDPresent << 6) & 0x40)
| ((pIE->IntType << 5) & 0x20)
| ((pIE->PrefExcl << 3) & 0x08)
| (pIE->InfoChanSel & 0x03);
/* Octet 3.1 - Interface Identifier */
if(pIE->IntIDPresent)
{
OBuf[(*Octet)++] = 0x80 | pIE->InterfaceID;
OBuf[(*Octet)++] = 0x80 | (pIE->InterfaceID & 0x7f);
}
else
{
@ -1263,12 +1294,21 @@ L3INT Q931Pie_ChanID(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3I
if(pIE->IntType == 1)
{
OBuf[(*Octet)++] = 0x80
| (pIE->CodStand << 5)
| (pIE->NumMap << 4)
| pIE->ChanMapType;
| ((pIE->CodStand << 5) & 0x60)
| ((pIE->NumMap << 4) & 0x10)
| (pIE->ChanMapType & 0x0f); /* TODO: support all possible channel map types */
/* Octet 3.2 Channel number/slot map */
OBuf[(*Octet)++] = 0x80 | pIE->ChanSlot;
/* Octet 3.3 Channel number */
switch(pIE->ChanMapType) {
case 0x6: /* Slot map: H0 Channel Units */ /* unsupported, Octets 3.3.1 - 3.3.3 */
return Q931E_CHANID;
case 0x8: /* Slot map: H11 Channel Units */
case 0x9: /* Slot map: H12 Channel Units */
default: /* Channel number */
OBuf[(*Octet)++] = 0x80 | (pIE->ChanSlot & 0x7f);
break;
}
}
}
@ -1302,28 +1342,25 @@ L3INT Q931Pie_ChanID(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3I
*****************************************************************************/
L3USHORT Q931Uie_CRV(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *IOff, L3INT *OOff)
{
L3USHORT CRV = 0;
L3INT Octet = *IOff;
L3INT l = IBuf[Octet];
L3USHORT CRV;
Octet++; /*Octet 2 is length indicator */
L3INT l = IBuf[Octet++];
if(l == 1) /* One octet CRV */
if(l == 1) /* One octet CRV */
{
CRV = IBuf[Octet] & 0x7F;
Octet++;
CRV = IBuf[Octet++] & 0x7F;
}
else if(l==2) /* two octet CRV */
else if(l == 2) /* two octet CRV */
{
CRV = (IBuf[Octet] & 0x7f) << 8;
CRV = CRV + IBuf[Octet+1];
Octet += 2;
CRV = (IBuf[Octet++] & 0x7f) << 8;
CRV |= IBuf[Octet++];
}
else
{
/* Long CRV is not used, so we skip this */
/* TODO: is it right to set to 0 here? */
CRV = 0;
Octet+=l;
/* Long CRV is not used, so we skip this */
/* TODO: is it right to set to 0 here? */
CRV = 0;
Octet += l;
}
*IOff = Octet;
@ -1634,7 +1671,7 @@ L3INT Q931Pie_HLComp(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3I
li=(*Octet)++;
/* Octet 3 */
OBuf[(*Octet)++] = 0x80 | (pIE->CodStand << 5) | (pIE->Interpret << 2) | pIE->PresMeth;
OBuf[(*Octet)++] = 0x80 | ((pIE->CodStand << 5) & 0x60) | ((pIE->Interpret << 2) & 0x1c) | (pIE->PresMeth & 0x03);
/* Octet 4 */
OBuf[(*Octet)++] = pIE->HLCharID;
@ -1642,11 +1679,11 @@ L3INT Q931Pie_HLComp(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3I
/* Octet 4a */
if(pIE->HLCharID == 0x5e || pIE->HLCharID == 0x5f)
{
OBuf[(*Octet)++] = 0x80 | pIE->EHLCharID;
OBuf[(*Octet)++] = 0x80 | (pIE->EHLCharID & 0x7f);
}
else if( pIE->HLCharID >= 0xc3 && pIE->HLCharID <= 0xcf)
{
OBuf[(*Octet)++] = 0x80 | pIE->EVideoTlfCharID;
OBuf[(*Octet)++] = 0x80 | (pIE->EVideoTlfCharID & 0x7f);
}
else
{
@ -3151,3 +3188,29 @@ L3INT Q931Pie_ChangeStatus(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBu
OBuf[li] = (L3UCHAR)((*Octet)-Beg) - 2;
return rc;
}
L3INT Q931Uie_Generic(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *pMsg, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *IOff, L3INT *OOff)
{
L3INT Octet = 0;
L3UCHAR id = 0;
/* id */
id = IBuf[Octet++];
/* Length */
Octet += IBuf[Octet];
Octet++;
Q931Log(pTrunk, Q931_LOG_DEBUG, "Discarding IE %#hhx with length %d\n", id, Octet - 2);
*IOff += Octet;
return Q931E_NO_ERROR;
}
L3INT Q931Pie_Generic(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet)
{
/* do nothing */
return Q931E_NO_ERROR;
}

View File

@ -43,6 +43,34 @@
#include "Q931.h"
/**
* Q931MesgHeader
* \brief Create Q.931 Message header
*/
L3INT Q931MesgHeader(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *mes, L3UCHAR *OBuf, L3INT Size, L3INT *IOff)
{
L3INT Octet = *IOff;
Q931Log(pTrunk, Q931_LOG_DEBUG, "Creating Q.931 Message Header:\n ProtDisc %d (%#x), CRV %d (%#x), CRVflag: %d (%#x), MesType: %d (%#x)\n",
mes->ProtDisc, mes->ProtDisc, mes->CRV, mes->CRV, mes->CRVFlag, mes->CRVFlag, mes->MesType, mes->MesType);
OBuf[Octet++] = mes->ProtDisc; /* Protocol discriminator */
if(!Q931_IS_BRI(pTrunk)) {
OBuf[Octet++] = 2; /* length is 2 octets */
OBuf[Octet++] = (L3UCHAR)((mes->CRV >> 8) & 0x7f) | ((mes->CRVFlag << 7) & 0x80); /* msb */
OBuf[Octet++] = (L3UCHAR) (mes->CRV & 0xff); /* lsb */
} else {
OBuf[Octet++] = 1; /* length is 1 octet */
OBuf[Octet++] = (L3UCHAR) (mes->CRV & 0x7f) | ((mes->CRVFlag << 7) & 0x80); /* CRV & flag */
}
OBuf[Octet++] = mes->MesType; /* message header */
*IOff = Octet;
return 0;
}
/*****************************************************************************
Function: Q931Umes_Alerting
@ -84,17 +112,12 @@ L3INT Q931Umes_Alerting(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic
*****************************************************************************/
L3INT Q931Pmes_Alerting(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize)
{
L3INT rc = Q931E_NO_ERROR;
L3INT rc = Q931E_NO_ERROR;
Q931mes_Generic *pMes = (Q931mes_Generic *)IBuf;
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);
/* Bearer capability */
if(Q931IsIEPresent(pMes->BearerCap))
@ -177,12 +200,7 @@ L3INT Q931Pmes_CallProceeding(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L
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);
/* Bearer capability */
if(Q931IsIEPresent(pMes->BearerCap))
@ -271,17 +289,23 @@ L3INT Q931Umes_Connect(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic
case Q931ie_SIGNAL:
case Q931ie_LOW_LAYER_COMPATIBILITY:
case Q931ie_HIGH_LAYER_COMPATIBILITY:
case Q931ie_CONNECTED_NUMBER: /* not actually used, seen while testing BRI PTMP TE */
rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff);
if(rc != Q931E_NO_ERROR)
return rc;
break;
default:
Q931Log(pTrunk, Q931_LOG_ERROR, "Illegal IE %#hhx in Connect Message\n", IBuf[IOff]);
return Q931E_ILLEGAL_IE;
break;
}
}
mes->Size = sizeof(Q931mes_Generic) - 1 + OOff;
return Q931E_NO_ERROR;
mes->Size = sizeof(Q931mes_Generic) - 1 + OOff;
return Q931E_NO_ERROR;
}
/*****************************************************************************
@ -296,12 +320,7 @@ L3INT Q931Pmes_Connect(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT IS
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);
/* Bearer capability */
if(Q931IsIEPresent(pMes->BearerCap))
@ -392,12 +411,7 @@ L3INT Q931Pmes_ConnectAck(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT
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);
/* Display */
if(Q931IsIEPresent(pMes->Display))
@ -432,6 +446,7 @@ L3INT Q931Umes_Disconnect(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Gener
case Q931ie_PROGRESS_INDICATOR:
case Q931ie_DISPLAY:
case Q931ie_SIGNAL:
case Q931ie_FACILITY:
rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff);
if(rc != Q931E_NO_ERROR)
return rc;
@ -457,12 +472,7 @@ L3INT Q931Pmes_Disconnect(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT
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);
/* Cause */
if(Q931IsIEPresent(pMes->Cause))
@ -516,8 +526,10 @@ L3INT Q931Umes_Information(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Gene
break;
}
}
mes->Size = sizeof(Q931mes_Generic) - 1 + OOff;
return Q931E_NO_ERROR;
mes->Size = sizeof(Q931mes_Generic) - 1 + OOff;
return Q931E_NO_ERROR;
}
/*****************************************************************************
@ -532,13 +544,8 @@ L3INT Q931Pmes_Information(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3IN
L3INT Octet = 0;
/* Q931 Message Header */
Q931MesgHeader(pTrunk, pMes, OBuf, *OSize, &Octet);
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 */
/* Sending Complete */
if(Q931IsIEPresent(pMes->SendComplete))
OBuf[Octet++] = (L3UCHAR)(pMes->SendComplete & 0x00ff);
@ -607,12 +614,7 @@ L3INT Q931Pmes_Notify(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISi
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);
/* Bearer capability */
if(Q931IsIEPresent(pMes->BearerCap))
@ -675,12 +677,7 @@ L3INT Q931Pmes_Progress(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);
/* Bearer capability */
if(Q931IsIEPresent(pMes->BearerCap))
@ -753,12 +750,7 @@ L3INT Q931Pmes_Release(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT IS
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);
/* Cause */
if(Q931IsIEPresent(pMes->Cause))
@ -820,12 +812,7 @@ L3INT Q931Pmes_ReleaseComplete(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf,
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);
/* Cause */
if(Q931IsIEPresent(pMes->Cause))
@ -882,34 +869,29 @@ L3INT Q931Umes_Restart(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic
*****************************************************************************/
L3INT Q931Pmes_Restart(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize)
{
L3INT rc = Q931E_NO_ERROR;
Q931mes_Generic *pMes = (Q931mes_Generic *)IBuf;
L3INT Octet = 0;
L3INT rc = Q931E_NO_ERROR;
Q931mes_Generic *pMes = (Q931mes_Generic *)IBuf;
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 */
/* ChanID */
if(Q931IsIEPresent(pMes->ChanID))
if((rc=Q931Pie[pTrunk->Dialect][Q931ie_CHANNEL_IDENTIFICATION](pTrunk, Q931GetIEPtr(pMes->ChanID,pMes->buf), OBuf, &Octet))!=0)
return rc;
/* Display */
if(Q931IsIEPresent(pMes->Display))
if((rc=Q931Pie[pTrunk->Dialect][Q931ie_DISPLAY](pTrunk, Q931GetIEPtr(pMes->Display,pMes->buf), OBuf, &Octet))!=0)
return rc;
/* RestartInd */
if(Q931IsIEPresent(pMes->RestartInd))
if((rc=Q931Pie[pTrunk->Dialect][Q931ie_RESTART_INDICATOR](pTrunk, Q931GetIEPtr(pMes->RestartInd,pMes->buf), OBuf, &Octet))!=0)
return rc;
/* Q931 Message Header */
Q931MesgHeader(pTrunk, pMes, OBuf, *OSize, &Octet);
/* ChanID */
if(Q931IsIEPresent(pMes->ChanID))
if((rc=Q931Pie[pTrunk->Dialect][Q931ie_CHANNEL_IDENTIFICATION](pTrunk, Q931GetIEPtr(pMes->ChanID,pMes->buf), OBuf, &Octet))!=0)
return rc;
/* Display */
if(Q931IsIEPresent(pMes->Display))
if((rc=Q931Pie[pTrunk->Dialect][Q931ie_DISPLAY](pTrunk, Q931GetIEPtr(pMes->Display,pMes->buf), OBuf, &Octet))!=0)
return rc;
/* RestartInd */
if(Q931IsIEPresent(pMes->RestartInd))
if((rc=Q931Pie[pTrunk->Dialect][Q931ie_RESTART_INDICATOR](pTrunk, Q931GetIEPtr(pMes->RestartInd,pMes->buf), OBuf, &Octet))!=0)
return rc;
*OSize = Octet;
return rc;
return rc;
}
/*****************************************************************************
@ -953,13 +935,8 @@ L3INT Q931Pmes_RestartAck(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT
Q931mes_Generic *pMes = (Q931mes_Generic *)IBuf;
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 */
/* Q931 Message Header */
Q931MesgHeader(pTrunk, pMes, OBuf, *OSize, &Octet);
/* ChanID */
if(Q931IsIEPresent(pMes->ChanID))
@ -1019,13 +996,8 @@ L3INT Q931Pmes_Resume(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISi
L3INT Octet = 0;
/* Q931 Message Header */
Q931MesgHeader(pTrunk, pMes, OBuf, *OSize, &Octet);
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 */
/* Call Identity */
if(Q931IsIEPresent(pMes->CallID))
if((rc=Q931Pie[pTrunk->Dialect][Q931ie_CALL_IDENTITY](pTrunk, Q931GetIEPtr(pMes->CallID,pMes->buf), OBuf, &Octet))!=0)
@ -1061,8 +1033,10 @@ L3INT Q931Umes_ResumeAck(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generi
break;
}
}
mes->Size = sizeof(Q931mes_Generic) - 1 + OOff;
return Q931E_NO_ERROR;
mes->Size = sizeof(Q931mes_Generic) - 1 + OOff;
return Q931E_NO_ERROR;
}
@ -1073,17 +1047,12 @@ L3INT Q931Umes_ResumeAck(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generi
*****************************************************************************/
L3INT Q931Pmes_ResumeAck(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize)
{
L3INT rc = Q931E_NO_ERROR;
L3INT rc = Q931E_NO_ERROR;
Q931mes_Generic *pMes = (Q931mes_Generic *)IBuf;
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);
/* Channel Identification */
if(Q931IsIEPresent(pMes->ChanID))
@ -1096,7 +1065,7 @@ L3INT Q931Pmes_ResumeAck(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT
*OSize = Octet;
return rc;
return rc;
}
/*****************************************************************************
@ -1124,8 +1093,10 @@ L3INT Q931Umes_ResumeReject(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Gen
break;
}
}
mes->Size = sizeof(Q931mes_Generic) - 1 + OOff;
return Q931E_NO_ERROR;
mes->Size = sizeof(Q931mes_Generic) - 1 + OOff;
return Q931E_NO_ERROR;
}
@ -1141,11 +1112,7 @@ L3INT Q931Pmes_ResumeReject(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3I
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);
/* Cause */
if(Q931IsIEPresent(pMes->Cause))
@ -1159,23 +1126,23 @@ L3INT Q931Pmes_ResumeReject(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3I
*OSize = Octet;
return rc;
return rc;
}
L3INT Q931Umes_Segment(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT OOff)
{
L3INT i = IOff;
L3INT i = IOff;
return IOff - i;
return IOff - i;
}
L3INT Q931Pmes_Segment(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize)
{
L3BOOL RetCode = L3FALSE;
L3BOOL RetCode = L3FALSE;
*OSize = 0;
return RetCode;
return RetCode;
}
/*****************************************************************************
@ -1196,6 +1163,7 @@ L3INT Q931Umes_Setup(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *m
case Q931ie_SENDING_COMPLETE:
IOff++;
break;
case Q931ie_BEARER_CAPABILITY:
case Q931ie_CHANNEL_IDENTIFICATION:
case Q931ie_PROGRESS_INDICATOR:
@ -1215,6 +1183,7 @@ L3INT Q931Umes_Setup(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *m
if(rc != Q931E_NO_ERROR)
return rc;
break;
case Q931ie_REPEAT_INDICATOR:
if(ir < 2) {
rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff);
@ -1223,13 +1192,16 @@ L3INT Q931Umes_Setup(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *m
return Q931E_ILLEGAL_IE;
}
break;
default:
return Q931E_ILLEGAL_IE;
break;
}
}
mes->Size = sizeof(Q931mes_Generic) - 1 + OOff;
return Q931E_NO_ERROR;
mes->Size = sizeof(Q931mes_Generic) - 1 + OOff;
return Q931E_NO_ERROR;
}
/*****************************************************************************
@ -1252,25 +1224,20 @@ L3INT Q931Umes_Setup(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *m
*****************************************************************************/
L3INT Q931Pmes_Setup(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize)
{
L3INT rc = Q931E_NO_ERROR;
L3INT rc = Q931E_NO_ERROR;
Q931mes_Generic *pMes = (Q931mes_Generic *)IBuf;
L3INT Octet = 0;
/* Q931 Message Header */
Q931MesgHeader(pTrunk, pMes, OBuf, *OSize, &Octet);
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 */
/* Sending Complete */
/* Sending Complete */
if(Q931IsIEPresent(pMes->SendComplete))
OBuf[Octet++] = (L3UCHAR)(pMes->SendComplete & 0x00ff);
OBuf[Octet++] = (L3UCHAR)Q931ie_SENDING_COMPLETE & 0xff;
/* Repeat Indicator */
if(Q931IsIEPresent(pMes->RepeatInd))
OBuf[Octet++] = (L3UCHAR)(pMes->RepeatInd & 0x00ff);
OBuf[Octet++] = (L3UCHAR)Q931ie_REPEAT_INDICATOR & 0xff;
/* Bearer capability */
if(Q931IsIEPresent(pMes->BearerCap))
@ -1359,7 +1326,7 @@ L3INT Q931Pmes_Setup(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISiz
*OSize = Octet;
return rc;
return rc;
}
/*****************************************************************************
@ -1389,8 +1356,8 @@ L3INT Q931Umes_SetupAck(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic
break;
}
}
mes->Size = sizeof(Q931mes_Generic) - 1 + OOff;
return Q931E_NO_ERROR;
mes->Size = sizeof(Q931mes_Generic) - 1 + OOff;
return Q931E_NO_ERROR;
}
/*****************************************************************************
@ -1405,12 +1372,7 @@ L3INT Q931Pmes_SetupAck(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);
/* Channel Identification */
if(Q931IsIEPresent(pMes->ChanID))
@ -1480,12 +1442,7 @@ L3INT Q931Pmes_Status(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISi
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);
/* Cause */
if(Q931IsIEPresent(pMes->Cause))
@ -1545,12 +1502,7 @@ L3INT Q931Pmes_StatusEnquiry(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3
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);
/* Display */
if(Q931IsIEPresent(pMes->Display))
@ -1602,12 +1554,7 @@ L3INT Q931Pmes_Suspend(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT IS
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);
/* Call Identity */
if(Q931IsIEPresent(pMes->CallID))
@ -1660,12 +1607,7 @@ L3INT Q931Pmes_SuspendAck(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT
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);
/* Display */
if(Q931IsIEPresent(pMes->Display))
@ -1718,12 +1660,7 @@ L3INT Q931Pmes_SuspendReject(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3
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);
/* Cause */
if(Q931IsIEPresent(pMes->Cause))
@ -1817,12 +1754,7 @@ L3INT Q931Pmes_Service(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT IS
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);
/* Display */
if(Q931IsIEPresent(pMes->ChanID))
@ -1883,12 +1815,7 @@ L3INT Q931Pmes_ServiceAck(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT
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);
if(Q931IsIEPresent(pMes->ChangeStatus))
if((rc=Q931Pie[pTrunk->Dialect][Q931ie_CHANGE_STATUS](pTrunk, Q931GetIEPtr(pMes->ChangeStatus,pMes->buf), OBuf, &Octet))!=0)

View File

@ -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);
#define INITIALIZED_MAGIC 42
struct Q921Data
typedef enum /* Type of connection */
{
Q921_PTP=0, /* 0 : Point-To-Point */
Q921_PTMP=1 /* 1 : Point-To-Multipoint */
} Q921NetType_t;
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 */
void Q921_InitTrunk(L2TRUNK trunk,
/* tei mgmt */
L2UCHAR tei_map[Q921_TEI_MAX]; /*!< */
L2UCHAR HDLCInQueue[Q921MAXHDLCSPACE]; /*!< HDLC input queue */
} Q921Data_t;
/*
* 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

View File

@ -0,0 +1,298 @@
/*****************************************************************************
FileName: Q921priv.h
Description: Private declarations
Created: 08.Aug.2008/STKN
License/Copyright:
Copyright (c) 2007, Jan Vidar Berger, Case Labs, Ltd. All rights reserved.
email:janvb@caselaboratories.com
Copyright (c) 2008, Stefan Knoblich, axsentis GmbH. All rights reserved.
email:s.knoblich@axsentis.de
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the Case Labs, Ltd nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef _Q921_PRIV_H_
#define _Q921_PRIV_H_
typedef enum /* Q.921 States */
{
Q921_STATE_STOPPED = 0, /* Trunk stopped */
Q921_STATE_TEI_UNASSIGNED = 1, /* TEI unassigned */
Q921_STATE_TEI_AWAITING, /* Assign awaiting TEI */
Q921_STATE_TEI_ESTABLISH, /* Establish awaiting TEI */
Q921_STATE_TEI_ASSIGNED, /* TEI assigned */
Q921_STATE_AWAITING_ESTABLISHMENT, /* Awaiting establishment */
Q921_STATE_AWAITING_RELEASE, /* Awaiting release */
Q921_STATE_MULTIPLE_FRAME_ESTABLISHED, /* Multiple frame established */
Q921_STATE_TIMER_RECOVERY /* Timer recovery */
} Q921State_t;
/*
* Flags
*/
enum Q921_Flags {
Q921_FLAG_L3_INITIATED = (1 << 0),
Q921_FLAG_UI_FRAME_QUEUED = (1 << 1),
Q921_FLAG_I_FRAME_QUEUED = (1 << 2),
Q921_FLAG_ACK_PENDING = (1 << 3),
Q921_FLAG_REJECT = (1 << 4),
Q921_FLAG_RECV_BUSY = (1 << 5),
Q921_FLAG_PEER_RECV_BUSY = (1 << 6)
};
#define Q921_SET_FLAG(x, f) ((x)->flags |= f)
#define Q921_CHECK_FLAG(x, f) ((x)->flags & f)
#define Q921_CLEAR_FLAG(x, f) ((x)->flags &= ~f)
/*
* dynamic TEI handling
*/
#define Q921_SAPI_TEI 63 /* SAPI for all TEI Messages */
#define Q921_LAYER_ENT_ID_TEI 0x0f /* UN Layer Management Entity ID for TEI Mgmt */
#define Q921_LAYER_ENT_ID_Q931 0x08 /* Q.931 Layer Management Entity ID */
typedef enum {
Q921_TEI_ID_REQUEST = 1,
Q921_TEI_ID_ASSIGNED,
Q921_TEI_ID_DENIED,
Q921_TEI_ID_CHECKREQ,
Q921_TEI_ID_CHECKRESP,
Q921_TEI_ID_REMOVE,
Q921_TEI_ID_VERIFY
} Q921TeiMessageType_t;
/**
* Per-Datalink context
*/
struct Q921_Link {
L2UCHAR tei; /*!< This endpoint's TEI */
L2UCHAR va;
L2UCHAR vs;
L2UCHAR vr;
L2INT flags;
Q921State_t state;
L2ULONG N202; /*!< PTMP TE mode retransmit counter */
L2ULONG N200; /*!< retransmit counter (per-TEI in PTMP NT mode) */
L2ULONG TM01; /*!< Datalink inactivity disconnect timer */
L2ULONG T200;
L2ULONG T201; /*!< PTMP NT mode timer */
L2ULONG T203;
L2USHORT ri; /*!< random id for TEI request mgmt */
/* I + UI Frame queue */
L2UCHAR UIFrameQueue[Q921MAXHDLCSPACE];
L2UCHAR IFrameQueue[Q921MAXHDLCSPACE];
L2UCHAR IFrameResendQueue[Q921MAXHDLCSPACE];
};
#define Q921_LINK_CONTEXT(tr, tei) \
(Q921_IS_PTMP_NT(tr) && tei != Q921_TEI_BCAST) ? ((struct Q921_Link *)&(tr)->context[tei]) : (tr)->context
#define Q921_TRUNK_CONTEXT(tr) \
(tr)->context
#define Q921_LOGBUFSIZE 2000
#define INITIALIZED_MAGIC 42
/*
* Helper macros
*/
#define Q921_INC_COUNTER(x) (x = (x + 1) % 128)
#define Q921_DEC_COUNTER(x) (x = (x) ? (x - 1) : 127)
#define Q921_UFRAME_HEADER_SIZE 3
#define Q921_UFRAME_DATA_OFFSET(tr) ((tr)->Q921HeaderSpace + Q921_UFRAME_HEADER_SIZE)
#define Q921_SFRAME_HEADER_SIZE 4
#define Q921_SFRAME_DATA_OFFSET(tr) ((tr)->Q921HeaderSpace + Q921_SFRAME_HEADER_SIZE)
#define Q921_IFRAME_HEADER_SIZE 4
#define Q921_IFRAME_DATA_OFFSET(tr) ((tr)->Q921HeaderSpace + Q921_IFRAME_HEADER_SIZE)
#define Q921_IS_TE(x) ((x)->NetUser == Q921_TE)
#define Q921_IS_NT(x) ((x)->NetUser == Q921_NT)
#define Q921_IS_STOPPED(tr) ((tr)->state == Q921_STATE_STOPPED)
/* TODO: rework this one */
#define Q921_IS_READY(tr) ((tr)->state >= Q921_STATE_TEI_ASSIGNED)
#define Q921_IS_PTMP(x) ((x)->NetType == Q921_PTMP)
#define Q921_IS_PTMP_TE(x) ((x)->NetType == Q921_PTMP && (x)->NetUser == Q921_TE)
#define Q921_IS_PTMP_NT(x) ((x)->NetType == Q921_PTMP && (x)->NetUser == Q921_NT)
#define Q921_IS_PTP(x) ((x)->NetType == Q921_PTP)
#define Q921_IS_PTP_TE(x) ((x)->NetType == Q921_PTP && (x)->NetUser == Q921_TE)
#define Q921_IS_PTP_NT(x) ((x)->NetType == Q921_PTP && (x)->NetUser == Q921_NT)
/* Make life a little easier */
#define Q921_COMMAND(x) ((x)->NetUser == Q921_TE ? 0 : 1)
#define Q921_RESPONSE(x) ((x)->NetUser == Q921_TE ? 1 : 0)
#define Q921_IS_COMMAND(tr, x) ((x) == (Q921_IS_TE(tr) ? 1 : 0))
#define Q921_IS_RESPONSE(tr, x) ((x) == (Q921_IS_TE(tr) ? 0 : 1))
/*******************************************************************************
* Private functions
*******************************************************************************/
/*
* L1 / L2 Interface
*/
static int Q921Tx21Proc(L2TRUNK trunk, L2UCHAR *Msg, L2INT size);
static int Q921Tx23Proc(L2TRUNK trunk, Q921DLMsg_t ind, L2UCHAR tei, L2UCHAR *Msg, L2INT size);
/*
* Timers
*/
static L2ULONG Q921GetTime(void);
static void Q921T200TimerStart(L2TRUNK trunk, L2UCHAR tei);
static void Q921T200TimerStop(L2TRUNK trunk, L2UCHAR tei);
static void Q921T200TimerReset(L2TRUNK trunk, L2UCHAR tei);
static void Q921T200TimerExpire(L2TRUNK trunk, L2UCHAR tei);
static void Q921T201TimerStart(L2TRUNK trunk, L2UCHAR tei);
static void Q921T201TimerStop(L2TRUNK trunk, L2UCHAR tei);
/* static void Q921T201TimerReset(L2TRUNK trunk, L2UCHAR tei); - Unused for now */
static void Q921T201TimerExpire(L2TRUNK trunk, L2UCHAR tei);
static void Q921T202TimerStart(L2TRUNK trunk);
static void Q921T202TimerStop(L2TRUNK trunk);
static void Q921T202TimerReset(L2TRUNK trunk);
static void Q921T202TimerExpire(L2TRUNK trunk);
static void Q921T203TimerStart(L2TRUNK trunk, L2UCHAR tei);
static void Q921T203TimerStop(L2TRUNK trunk, L2UCHAR tei);
static void Q921T203TimerReset(L2TRUNK trunk, L2UCHAR tei);
static void Q921T203TimerExpire(L2TRUNK trunk, L2UCHAR tei);
static void Q921TM01TimerStart(L2TRUNK trunk, L2UCHAR tei);
/* static void Q921TM01TimerStop(L2TRUNK trunk, L2UCHAR tei); - Unused for now */
static void Q921TM01TimerReset(L2TRUNK trunk, L2UCHAR tei);
/* static void Q921TM01TimerExpire(L2TRUNK trunk, L2UCHAR tei); - Unused for now */
/*
* Frame encoding
*/
static int Q921SendS(L2TRUNK trunk, L2UCHAR Sapi, char cr, L2UCHAR Tei, char pf, L2UCHAR sv, L2UCHAR *mes, L2INT size);
static int Q921SendU(L2TRUNK trunk, L2UCHAR Sapi, char cr, L2UCHAR Tei, char pf, L2UCHAR m, L2UCHAR *mes, L2INT size);
static int Q921SendRNR(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf);
static int Q921SendREJ(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf);
static int Q921SendSABME(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf);
static int Q921SendDM(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf);
static int Q921SendDISC(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf);
static int Q921SendUA(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf);
static int Q921SendUN(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf, L2UCHAR *mes, L2INT size);
static int Q921SendRR(L2TRUNK trunk, int Sapi, int cr, int Tei, int pf);
/*
* Frame decoding
*/
static int Q921ProcIFrame(L2TRUNK trunk, L2UCHAR *mes, L2INT size);
static int Q921ProcSFrame(L2TRUNK trunk, L2UCHAR *mes, L2INT size);
static int Q921ProcUFrame(L2TRUNK trunk, L2UCHAR *mes, L2INT size);
static int Q921ProcSABME(L2TRUNK trunk, L2UCHAR *mes, L2INT size);
static int Q921ProcDM(L2TRUNK trunk, L2UCHAR *mes, L2INT size);
static int Q921ProcUA(L2TRUNK trunk, L2UCHAR *mes, L2INT size);
static int Q921ProcDISC(L2TRUNK trunk, L2UCHAR *mes, L2INT size);
static int Q921ProcRR(L2TRUNK trunk, L2UCHAR *mes, L2INT size);
static int Q921ProcRNR(L2TRUNK trunk, L2UCHAR *mes, L2INT size);
static int Q921ProcREJ(L2TRUNK trunk, L2UCHAR *mes, L2INT size);
/*
* (Common) procedures defined in the Q.921 SDL
*/
static int Q921SendEnquiry(L2TRUNK trunk, L2UCHAR tei);
static int Q921SendEnquiryResponse(L2TRUNK trunk, L2UCHAR tei);
static void Q921ResetExceptionConditions(L2TRUNK trunk, L2UCHAR tei);
static int Q921EstablishDataLink(L2TRUNK trunk, L2UCHAR tei);
static int Q921NrErrorRecovery(L2TRUNK trunk, L2UCHAR tei);
static int Q921InvokeRetransmission(L2TRUNK trunk, L2UCHAR tei, L2UCHAR nr);
static int Q921AcknowledgePending(L2TRUNK trunk, L2UCHAR tei);
/*
static int Q921SetReceiverBusy(L2TRUNK trunk);
static int Q921ClearReceiverBusy(L2TRUNK trunk);
*/
/*
* Queueing
*/
static int Q921SendQueuedIFrame(L2TRUNK trunk, L2UCHAR tei);
static int Q921EnqueueI(L2TRUNK trunk, L2UCHAR Sapi, char cr, L2UCHAR Tei, char pf, L2UCHAR *mes, L2INT size);
/*
* TEI management
*/
static int Q921TeiSendAssignRequest(L2TRUNK trunk);
static int Q921TeiProcAssignResponse(L2TRUNK trunk, L2UCHAR *mes, L2INT size);
static int Q921TeiSendVerifyRequest(L2TRUNK trunk);
static int Q921TeiProcCheckRequest(L2TRUNK trunk, L2UCHAR *mes, L2INT size);
static int Q921TeiProcRemoveRequest(L2TRUNK trunk, L2UCHAR *mes, L2INT size);
static int Q921TeiProcAssignRequest(L2TRUNK trunk, L2UCHAR *mes, L2INT size);
static int Q921TeiProcCheckResponse(L2TRUNK trunk, L2UCHAR *mes, L2INT size);
static int Q921TeiProcVerifyRequest(L2TRUNK trunk, L2UCHAR *mes, L2INT size);
static int Q921TeiSendRemoveRequest(L2TRUNK trunk, L2UCHAR tei);
static int Q921TeiSendDenyResponse(L2TRUNK trunk, L2UCHAR tei, L2USHORT ri);
static int Q921TeiSendAssignedResponse(L2TRUNK trunk, L2UCHAR tei, L2USHORT ri);
static int Q921TeiSendCheckRequest(L2TRUNK trunk, L2UCHAR tei);
/*
* Logging
*/
static int Q921Log(L2TRUNK trunk, Q921LogLevel_t level, const char *fmt, ...);
static int Q921LogMesg(L2TRUNK trunk, Q921LogLevel_t level, L2UCHAR received, L2UCHAR *mes, L2INT size, const char *fmt, ...);
/*
* State handling
*/
static int Q921ChangeState(L2TRUNK trunk, Q921State_t state, L2UCHAR tei);
#endif

View File

@ -244,23 +244,35 @@ typedef L3USHORT ie; /* Special data type to hold a dynamic */
*****************************************************************************/
#define Q931L4BUF 1000 /* size of message buffer */
#define Q931_LOGBUFSIZE 1024 /* size of logging buffer */
#define Q931L2BUF 300 /* size of message buffer */
#define Q931L4BUF 1000 /* size of message buffer */
#define Q931MAXTRUNKS 4 /* Total number of trunks that will be */
/* processed by this instance of the */
/* stack */
#define Q931L2BUF 300 /* size of message buffer */
#define Q931MAXCHPERTRUNK 32 /* Number of channels per trunk. The */
/* stack uses a static set of 32 */
/* channels regardless if it is E1, T1 */
/* or BRI that actually is used. */
#define Q931MAXTRUNKS 4 /* Total number of trunks that will be */
/* processed by this instance of the */
/* stack */
#define Q931MAXCALLPERTRUNK (Q931MAXCHPERTRUNK * 2)
/* Number of max active CRV per trunk. */
/* Q.931 can have more calls than there */
/* are channels. */
#define Q931MAXCHPERTRUNK 32 /* Number of channels per trunk. The */
/* stack uses a static set of 32 */
/* channels regardless if it is E1, T1 */
/* or BRI that actually is used. */
#define Q931MAXCALLPERTRUNK (Q931MAXCHPERTRUNK * 2)
/* Number of max active CRV per trunk. */
/* Q.931 can have more calls than there */
/* are channels. */
#define Q931_IS_BRI(x) ((x)->TrunkType == Q931_TrType_BRI || (x)->TrunkType == Q931_TrType_BRI_PTMP)
#define Q931_IS_PRI(x) (!Q931_IS_BRI(x))
#define Q931_IS_PTP(x) ((x)->TrunkType != Q931_TrType_BRI_PTMP)
#define Q931_IS_PTMP(X) ((x)->TrunkType == Q931_TrType_BRI_PTMP)
#define Q931_BRI_MAX_CRV 127
#define Q931_PRI_MAX_CRV 32767
/*****************************************************************************
@ -280,24 +292,19 @@ typedef L3USHORT ie; /* Special data type to hold a dynamic */
*****************************************************************************/
/* WARNING! Initialize Q931CreateDialectCB[] will NULL when increasing the */
/* Q931MAXDLCT value to avoid Q931Initialize from crashing if one entry is */
/* not used. */
#define Q931MAXDLCT 8 /* Max dialects included in this */
/* compile. User and Network count as */
/* one dialect each. */
#define Q931MAXMES 128 /* Number of messages */
#define Q931MAXIE 255 /* Number of IE */
#define Q931MAXUSEDIE 50 /* Maximum number of ie types per Dialect */
#define Q931MAXCODESETS 7 /* Maximum number of codests (by spec, 0-7) */
#define Q931MAXSTATE 100 /* Size of state tables */
/* WARNING! Initialize Q931CreateDialectCB[] will NULL when increasing the */
/* Q931MAXDLCT value to avoid Q931Initialize from crashing if one entry is */
/* not used. */
#define Q931MAXDLCT 8 /* Max dialects included in this */
/* compile. User and Network count as */
/* one dialect each. */
#define Q931MAXMES 128 /* Number of messages */
#define Q931MAXIE 255 /* Number of IE */
#define Q931MAXUSEDIE 50 /* Maximum number of ie types per Dialect */
#define Q931MAXCODESETS 7 /* Maximum number of codests (by spec, 0-7) */
#define Q931MAXSTATE 100 /* Size of state tables */
#define Q931MAXTIMER 25 /* Maximum number of timers */
/*****************************************************************************
@ -381,6 +388,155 @@ typedef L3USHORT ie; /* Special data type to hold a dynamic */
#define Q931mes_SERVICE_ACKNOWLEDGE 0x07 /* 0000 0111 */
/**
* Generic Q.931 Timers
*/
enum {
Q931_TIMER_T300 = 1, /* */
Q931_TIMER_T301,
Q931_TIMER_T302,
Q931_TIMER_T303,
Q931_TIMER_T304,
Q931_TIMER_T305,
Q931_TIMER_T306,
Q931_TIMER_T307,
Q931_TIMER_T308,
Q931_TIMER_T309,
Q931_TIMER_T310,
Q931_TIMER_T311,
Q931_TIMER_T312,
Q931_TIMER_T313,
Q931_TIMER_T314,
Q931_TIMER_T315,
Q931_TIMER_T316,
Q931_TIMER_T317,
Q931_TIMER_T318,
Q931_TIMER_T319,
Q931_TIMER_T320,
Q931_TIMER_T321,
Q931_TIMER_T322,
};
/**
* Q.931 ToN
*/
enum {
Q931_TON_UNKNOWN = 0x00,
Q931_TON_INTERNATIONAL = 0x01,
Q931_TON_NATIONAL = 0x02,
Q931_TON_NETWORK_SPECIFIC = 0x03,
Q931_TON_SUBSCRIBER_NUMBER = 0x04,
Q931_TON_ABBREVIATED_NUMBER = 0x06,
Q931_TON_RESERVED = 0x07
};
/**
* Q.931 Numbering Plan
*/
enum {
Q931_NUMPLAN_UNKNOWN = 0x00,
Q931_NUMPLAN_E164 = 0x01,
Q931_NUMPLAN_X121 = 0x03,
Q931_NUMPLAN_F69 = 0x04,
Q931_NUMPLAN_NATIONAL = 0x08,
Q931_NUMPLAN_PRIVATE = 0x09,
Q931_NUMPLAN_RESERVED = 0x0e
};
/**
* Q.931 Presentation Indicator
*/
enum {
Q931_PRES_ALLOWED = 0x00,
Q931_PRES_RESTRICTED = 0x01,
Q931_PRES_NOT_AVAILABLE = 0x02,
Q931_PRES_RESERVED = 0x03
};
/**
* Q.931 Screening Indicator
*/
enum {
Q931_SCREEN_USER_NOT_SCREENED = 0x00,
Q931_SCREEN_USER_VERIFIED_PASSED = 0x01,
Q931_SCREEN_USER_VERIFIED_FAILED = 0x02,
Q931_SCREEN_NETWORK = 0x03
};
/**
* Q.931 Coding Standard
*/
enum {
Q931_CODING_ITU = 0x00,
Q931_CODING_ISO = 0x01,
Q931_CODING_NATIONAL = 0x02,
Q931_CODING_NETWORK = 0x03
};
/**
* Q.931 High layer characteristik id
*/
enum {
Q931_HLCHAR_TELEPHONY = 0x01,
Q931_HLCHAR_FAX_G23 = 0x04,
Q931_HLCHAR_FAX_G4 = 0x21,
Q931_HLCHAR_FAX_G4II = 0x24,
Q931_HLCHAR_T102 = 0x32,
Q931_HLCHAR_T101 = 0x33,
Q931_HLCHAR_F60 = 0x35,
Q931_HLCHAR_X400 = 0x38,
Q931_HLCHAR_X200 = 0x41
};
/**
* Q.931 User information layer 1 protocol
*/
enum {
Q931_UIL1P_V110 = 0x01,
Q931_UIL1P_I460 = 0x01,
Q931_UIL1P_X30 = 0x01,
Q931_UIL1P_G711U = 0x02,
Q931_UIL1P_G711A = 0x03,
Q931_UIL1P_G721 = 0x04,
Q931_UIL1P_H221 = 0x05,
Q931_UIL1P_H242 = 0x05,
Q931_UIL1P_H223 = 0x06,
Q931_UIL1P_H245 = 0x06,
Q931_UIL1P_RATE_ADAP = 0x07,
Q931_UIL1P_V120 = 0x08,
Q931_UIL1P_X31 = 0x09
};
/**
* Q.931 Information Transfer Capability
*/
enum {
Q931_ITC_SPEECH = 0x00,
Q931_ITC_UNRESTRICTED = 0x08,
Q931_ITC_RESTRICTED = 0x09,
Q931_ITC_3K1_AUDIO = 0x10,
Q931_ITC_UNRESTRICTED_TONES = 0x11,
Q931_ITC_VIDEO = 0x18
};
/**
* Q.931 Information transfer rate
*/
enum {
Q931_ITR_PACKET = 0x00,
Q931_ITR_64K = 0x10,
Q931_ITR_128K = 0x11,
Q931_ITR_384K = 0x13,
Q931_ITR_1536K = 0x15,
Q931_ITR_1920K = 0x17,
Q931_ITR_MULTI = 0x18
};
/*****************************************************************************
Struct: Q931mes_Header
@ -479,33 +635,46 @@ typedef struct
*****************************************************************************/
typedef struct Q931_TrunkInfo Q931_TrunkInfo_t;
typedef L3INT (*Q931TxCB_t) (void *,L3UCHAR *, L3INT);
typedef L3INT (*Q931ErrorCB_t) (void *,L3INT,L3INT,L3INT);
typedef enum /* Network/User Mode. */
typedef enum
{
Q931_TE=0, /* 0 : User Mode */
Q931_NT=1 /* 1 : Network Mode */
Q931_LOG_NONE = 0,
Q931_LOG_ERROR,
Q931_LOG_WARNING,
Q931_LOG_NOTICE,
Q931_LOG_INFO,
Q931_LOG_DEBUG
} Q931LogLevel_t;
typedef L3INT (*Q931Tx34CB_t) (void *,L3UCHAR *, L3INT);
typedef L3INT (*Q931Tx32CB_t) (void *, L3INT, L3UCHAR, L3UCHAR *, L3INT);
typedef L3INT (*Q931ErrorCB_t) (void *,L3INT,L3INT,L3INT);
typedef L3INT (*Q931LogCB_t) (void *, Q931LogLevel_t, char *, L3INT);
typedef enum /* Network/User Mode. */
{
Q931_TE=0, /* 0 : User Mode */
Q931_NT=1 /* 1 : Network Mode */
} Q931NetUser_t;
typedef enum /* Dialect enum */
typedef enum /* Dialect enum */
{
Q931_Dialect_Q931 = 0,
Q931_Dialect_National = 2,
Q931_Dialect_DMS = 4,
Q931_Dialect_5ESS = 6, /* Coming soon to a PRI stack near you! */
Q931_Dialect_5ESS = 6, /* Coming soon to a PRI stack near you! */
Q931_Dialect_Count
} Q931Dialect_t;
#define DIALECT_STRINGS "q931", "", "national", "", "dms","","5ess",""
#define DIALECT_STRINGS "q931", "", "national", "", "dms", "", "5ess", ""
Q931_STR2ENUM_P(q931_str2Q931Dialect_type, q931_Q931Dialect_type2str, Q931Dialect_t)
typedef enum /* Trunk Line Type. */
typedef enum /* Trunk Line Type. */
{
Q931_TrType_E1=0, /* 0 : E1 Trunk */
Q931_TrType_T1=1, /* 1 : T1 Trunk */
Q931_TrType_J1=2, /* 2 : J1 Trunk */
Q931_TrType_BRI=3 /* 3 : BRI Trunk */
Q931_TrType_E1 = 0, /* 0 : E1 Trunk */
Q931_TrType_T1 = 1, /* 1 : T1 Trunk */
Q931_TrType_J1 = 2, /* 2 : J1 Trunk */
Q931_TrType_BRI = 3, /* 3 : BRI Trunk */
Q931_TrType_BRI_PTMP = 4 /* 4 : BRI PTMP Trunk */
} Q931_TrunkType_t;
typedef enum /* Trunk State */
@ -522,19 +691,51 @@ typedef enum {
Q931_ChType_Sync=3 /* Sync Channel */
} Q931_ChanType_t;
struct Q931_Call
{
L3UCHAR InUse; /* Indicate if entry is in use. */
/* 0 = Not in Use */
/* 1 = Active Call. */
L3UCHAR Tei; /* Associated TEI */
L3UCHAR BChan; /* Associated B Channel. */
/* 0 - 31 valid B chan */
/* 255 = Not allocated */
L3INT CRV; /* Associated CRV. */
L3UINT State; /* Call State. */
/* 0 is Idle, but other values are */
/* defined per dialect. */
/* Default usage is 1-99 for TE and */
/* 101 - 199 for NT. */
L3ULONG Timer; /* Timer in ms. The TimeTick will check */
/* if this has exceeded the timeout, and */
/* if so call the timers timeout proc. */
L3USHORT TimerID; /* Timer Identification/State */
/* actual values defined by dialect */
/* 0 : No timer running */
/* ITU-T Q.931:301 - 322 Timer running */
};
struct Q931_TrunkInfo
{
Q931NetUser_t NetUser; /* Network/User Mode. */
Q931Dialect_t Dialect; /* Q.931 Based dialect index. */
Q931_TrunkType_t TrunkType; /* Trunk Line Type. */
Q931Dialect_t Dialect; /* Q.931 Based dialect index. */
Q931TxCB_t Q931Tx34CBProc;
Q931TxCB_t Q931Tx32CBProc;
Q931Tx34CB_t Q931Tx34CBProc;
Q931Tx32CB_t Q931Tx32CBProc;
Q931ErrorCB_t Q931ErrorCBProc;
Q931LogCB_t Q931LogCBProc;
void *PrivateData32;
void *PrivateData34;
void *PrivateDataLog;
Q931LogLevel_t loglevel;
L3UCHAR Enabled; /* Enabled/Disabled */
/* 0 = Disabled */
@ -580,37 +781,9 @@ struct Q931_TrunkInfo
}ch[Q931MAXCHPERTRUNK];
/* Active Call information indentified by CRV. See Q931AllocateCRV for */
/* initialization of call table. */
struct _ccarray
{
L3UCHAR InUse; /* Indicate if entry is in use. */
/* 0 = Not in Use */
/* 1 = Active Call. */
L3UCHAR BChan; /* Associated B Channel. */
/* 0 - 31 valid B chan */
/* 255 = Not allocated */
L3INT CRV; /* Associated CRV. */
L3UINT State; /* Call State. */
/* 0 is Idle, but other values are */
/* defined per dialect. */
/* Default usage is 1-99 for TE and */
/* 101 - 199 for NT. */
L3ULONG Timer; /* Timer in ms. The TimeTick will check */
/* if this has exceeded the timeout, and*/
/* if so call the timers timeout proc. */
L3USHORT TimerID; /* Timer Identification/State */
/* actual values defined by dialect */
/* 0 : No timer running */
/* ITU-T Q.931:301 - 322 Timer running */
}call[Q931MAXCALLPERTRUNK];
/* Active Call information indentified by CRV. See Q931AllocateCRV for */
/* initialization of call table. */
struct Q931_Call call[Q931MAXCALLPERTRUNK];
};
/*****************************************************************************
@ -646,6 +819,9 @@ typedef L3INT (q931pmes_func_t) (Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf
typedef L3INT (q931uie_func_t) (Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff);
typedef L3INT (q931pie_func_t) (Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet);
typedef L3INT (q931timeout_func_t) (Q931_TrunkInfo_t *pTrunk, L3INT callIndex);
typedef L3ULONG q931timer_t;
extern q931proc_func_t *Q931Proc[Q931MAXDLCT][Q931MAXMES];
extern q931umes_func_t *Q931Umes[Q931MAXDLCT][Q931MAXMES];
@ -654,6 +830,10 @@ extern q931pmes_func_t *Q931Pmes[Q931MAXDLCT][Q931MAXMES];
extern q931uie_func_t *Q931Uie[Q931MAXDLCT][Q931MAXIE];
extern q931pie_func_t *Q931Pie[Q931MAXDLCT][Q931MAXIE];
extern q931timeout_func_t *Q931Timeout[Q931MAXDLCT][Q931MAXTIMER];
extern q931timer_t Q931Timer[Q931MAXDLCT][Q931MAXTIMER];
/*****************************************************************************
Macro: GetIETotoSize
@ -893,9 +1073,9 @@ L3INT Q931ProcUnexpectedMessage(Q931_TrunkInfo_t *pTrunk,L3UCHAR * b, L3INT iFro
Interface Function Prototypes. Implemented in Q931.c
*****************************************************************************/
void Q931TimeTick(Q931_TrunkInfo_t *pTrunk, L3ULONG ms);
L3INT Q931Rx23(Q931_TrunkInfo_t *pTrunk, L3UCHAR * Mes, L3INT Size);
L3INT Q931Tx32(Q931_TrunkInfo_t *pTrunk, L3UCHAR * Mes, L3INT Size);
void Q931TimerTick(Q931_TrunkInfo_t *pTrunk);
L3INT Q931Rx23(Q931_TrunkInfo_t *pTrunk, L3INT ind, L3UCHAR tei, L3UCHAR * Mes, L3INT Size);
L3INT Q931Tx32Data(Q931_TrunkInfo_t *pTrunk, L3UCHAR bcast, L3UCHAR * Mes, L3INT Size);
L3INT Q931Rx43(Q931_TrunkInfo_t *pTrunk, L3UCHAR * Mes, L3INT Size);
L3INT Q931Tx34(Q931_TrunkInfo_t *pTrunk, L3UCHAR * Mes, L3INT Size);
void Q931SetError(Q931_TrunkInfo_t *pTrunk,L3INT ErrID, L3INT ErrPar1, L3INT ErrPar2);
@ -910,6 +1090,8 @@ void Q931SetHeaderSpace(L3INT space);
void Q931SetMesProc(L3UCHAR mes, L3UCHAR dialect, q931proc_func_t *Q931ProcFunc, q931umes_func_t *Q931UmesFunc, q931pmes_func_t *Q931PmesFunc);
void Q931SetIEProc(L3UCHAR iec, L3UCHAR dialect, q931pie_func_t *Q931PieProc, q931uie_func_t *Q931UieProc);
void Q931SetTimeoutProc(L3UCHAR timer, L3UCHAR dialect, q931timeout_func_t *Q931TimeoutProc);
void Q931SetTimerDefault(L3UCHAR timer, L3UCHAR dialect, q931timer_t timeout);
void Q931Initialize(void);
void Q931AddDialect(L3UCHAR iDialect, void (*Q931CreateDialectCB)(L3UCHAR iDialect));
@ -926,7 +1108,7 @@ L3INT Q931StartTimer(Q931_TrunkInfo_t *pTrunk, L3INT callIndex, L3USHORT iTimer)
L3INT Q931StopTimer(Q931_TrunkInfo_t *pTrunk, L3INT callindex, L3USHORT iTimer);
L3INT Q931SetState(Q931_TrunkInfo_t *pTrunk, L3INT callIndex, L3INT iState);
L3ULONG Q931GetTime(void);
void Q931SetGetTimeCB(L3ULONG (*callback)(void));
void Q931SetGetTimeCB(L3ULONG (*callback)(void));
void Q931AddStateEntry(L3UCHAR iD, L3INT iState, L3INT iMes, L3UCHAR cDir);
L3BOOL Q931IsEventLegal(L3UCHAR iD, L3INT iState, L3INT iMes, L3UCHAR cDir);
@ -965,8 +1147,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);
@ -974,7 +1156,9 @@ L3INT Q931Api_InitTrunk(Q931_TrunkInfo_t *pTrunk,
L3INT Q931GetMesSize(Q931mes_Generic *pMes);
L3INT Q931InitMesResume(Q931mes_Generic * pMes);
L3INT Q931Log(Q931_TrunkInfo_t *trunk, Q931LogLevel_t level, const char *fmt, ...);
void Q931SetLogCB(Q931_TrunkInfo_t *trunk, Q931LogCB_t func, void *priv);
void Q931SetLogLevel(Q931_TrunkInfo_t *trunk, Q931LogLevel_t level);
void Q931SetL4HeaderSpace(L3INT space);
void Q931SetL2HeaderSpace(L3INT space);
@ -985,7 +1169,8 @@ L3INT Q931PmesDummy(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize
L3INT Q931PieDummy(Q931_TrunkInfo_t *pTrunk,L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet);
L3INT Q931TxDummy(Q931_TrunkInfo_t *pTrunk, L3UCHAR * b, L3INT n);
L3INT Q931ErrorDummy(void *priv, L3INT a, L3INT b, L3INT c);
L3INT Q931TimeoutDummy(Q931_TrunkInfo_t *pTrunk, L3INT callIndex);
L3INT Q931MesgHeader(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *mes, L3UCHAR *OBuf, L3INT Size, L3INT *IOff);
#endif /* _Q931_NL */

View File

@ -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 */

View File

@ -58,15 +58,15 @@ typedef struct _mindex
queue.
*****************************************************************************/
typedef struct _mfifo
typedef struct
{
int first; /* first out */
int last; /* last in + 1 */
int bsize; /* buffer size */
unsigned char *buf; /* ptr to start of buffer */
int ixsize; /* index size */
MINDEX ix[1]; /* message index */
}MFIFO;
unsigned char *buf; /* ptr to start of buffer */
int ixsize; /* index size */
MINDEX ix[1]; /* message index */
} MFIFO;
/*****************************************************************************
Function prototypes.
@ -80,4 +80,8 @@ int MFIFOWriteMes(unsigned char *buf, unsigned char *mes, int size);
unsigned char * MFIFOGetMesPtr(unsigned char *buf, int *size);
void MFIFOKillNext(unsigned char *buf);
unsigned char * MFIFOGetMesPtrOffset(unsigned char *buf, int *size, const int pos);
int MFIFOGetMesCount(unsigned char *buf);
int MFIFOWriteMesOverwrite(unsigned char *buf, unsigned char *mes, int size);
#endif

View File

@ -84,17 +84,16 @@
*****************************************************************************/
int MFIFOCreate(unsigned char *buf, int size, int index)
{
MFIFO * mf;
mf = (MFIFO*)buf;
MFIFO *mf = (MFIFO *)buf;
mf->first = mf->last = 0;
mf->ixsize = index;
mf->buf = &buf[sizeof(MFIFO) + (sizeof(MINDEX) * (index-1))];
mf->buf = &buf[sizeof(MFIFO) + (sizeof(MINDEX) * index)];
if(mf->buf > & buf[size])
if(mf->buf > &buf[size])
return 0;
mf->bsize = size - sizeof(MFIFO) - (sizeof(MINDEX) * (index-1));
mf->bsize = size - sizeof(MFIFO) - (sizeof(MINDEX) * index);
return 1;
}
@ -112,9 +111,9 @@ int MFIFOCreate(unsigned char *buf, int size, int index)
*****************************************************************************/
void MFIFOClear(unsigned char * buf)
{
MFIFO * mf;
mf = (MFIFO*)buf;
mf->first = mf->last = 0;
MFIFO *mf = (MFIFO *)buf;
mf->first = mf->last = 0;
}
/*****************************************************************************
@ -130,8 +129,8 @@ void MFIFOClear(unsigned char * buf)
*****************************************************************************/
int MFIFOGetLBOffset(unsigned char *buf)
{
MFIFO * mf;
mf = (MFIFO*)buf;
MFIFO *mf = (MFIFO *)buf;
if(mf->last != mf->first)
return mf->ix[mf->last].offset;
@ -153,15 +152,17 @@ int MFIFOGetLBOffset(unsigned char *buf)
*****************************************************************************/
int MFIFOGetFBOffset(unsigned char *buf)
{
MFIFO *mf = (MFIFO *)buf;
int x;
MFIFO * mf;
mf = (MFIFO*)buf;
if(mf->last == mf->first)
return 0;
x=mf->first;
x--;
if(x<0)
x=mf->ixsize;
x = mf->first - 1;
if(x < 0)
x = mf->ixsize - 1;
return mf->ix[x].offset + mf->ix[x].size;
}
@ -184,16 +185,19 @@ int MFIFOGetFBOffset(unsigned char *buf)
*****************************************************************************/
void MFIFOWriteIX(unsigned char *buf, unsigned char *mes, int size, int ix, int off)
{
MFIFO *mf = (MFIFO *)buf;
int x;
MFIFO * mf;
mf = (MFIFO*)buf;
memcpy(&mf->buf[off],mes,size);
mf->ix[ix].offset=off;
mf->ix[ix].size=size;
x = mf->first+1;
if(x > mf->ixsize)
x=0;
mf->first=x;
memcpy(&mf->buf[off], mes, size);
mf->ix[ix].offset = off;
mf->ix[ix].size = size;
x = mf->first + 1;
if(x >= mf->ixsize)
x = 0;
mf->first = x;
}
/*****************************************************************************
@ -209,13 +213,14 @@ void MFIFOWriteIX(unsigned char *buf, unsigned char *mes, int size, int ix, int
*****************************************************************************/
int MFIFOWriteMes(unsigned char *buf, unsigned char *mes, int size)
{
int of,ol,x;
MFIFO * mf;
mf = (MFIFO*)buf;
MFIFO *mf = (MFIFO *)buf;
int of, ol, x;
x = mf->first + 1;
if(x >= mf->ixsize)
x = 0;
x = mf->first+1;
if(x > mf->ixsize)
x=0;
if(x == mf->last)
return 0; /* full queue */
@ -224,6 +229,7 @@ int MFIFOWriteMes(unsigned char *buf, unsigned char *mes, int size)
if(mf->last == mf->first) /* empty queue */
{
mf->first = mf->last = 0; /* optimize */
MFIFOWriteIX(buf, mes, size, mf->first, 0);
return 1;
}
@ -231,18 +237,18 @@ int MFIFOWriteMes(unsigned char *buf, unsigned char *mes, int size)
{
if(mf->bsize - of >= size)
{
MFIFOWriteIX(buf,mes,size,mf->first,of);
MFIFOWriteIX(buf, mes, size, mf->first, of);
return 1;
}
else if(ol > size)
{
MFIFOWriteIX(buf,mes,size,mf->first,ol);
MFIFOWriteIX(buf, mes, size, mf->first, ol);
return 1;
}
}
else if(ol - of > size)
{
MFIFOWriteIX(buf,mes,size,mf->first,of);
MFIFOWriteIX(buf, mes, size, mf->first, of);
return 1;
}
@ -262,12 +268,14 @@ int MFIFOWriteMes(unsigned char *buf, unsigned char *mes, int size)
*****************************************************************************/
unsigned char * MFIFOGetMesPtr(unsigned char *buf, int *size)
{
MFIFO * mf;
mf = (MFIFO*)buf;
if(mf->first==mf->last)
return NULL;
*size = mf->ix[mf->last].size;
return &mf->buf[mf->ix[mf->last].offset];
MFIFO *mf = (MFIFO *)buf;
if(mf->first == mf->last) {
return NULL;
}
*size = mf->ix[mf->last].size;
return &mf->buf[mf->ix[mf->last].offset];
}
/*****************************************************************************
@ -283,14 +291,120 @@ unsigned char * MFIFOGetMesPtr(unsigned char *buf, int *size)
*****************************************************************************/
void MFIFOKillNext(unsigned char *buf)
{
MFIFO *mf = (MFIFO *)buf;
int x;
MFIFO * mf;
mf = (MFIFO*)buf;
if(mf->first!=mf->last)
if(mf->first != mf->last)
{
x = mf->last+1;
if(x > mf->ixsize)
x=0;
mf->last=x;
x = mf->last + 1;
if(x >= mf->ixsize) {
x = 0;
}
mf->last = x;
}
}
/*
* Queue-style accessor functions
*/
/**
* MFIFOGetMesPtrOffset
* \brief Get pointer to and size of message at position x
*/
unsigned char * MFIFOGetMesPtrOffset(unsigned char *buf, int *size, const int pos)
{
MFIFO *mf = (MFIFO *)buf;
int x;
if(mf->first == mf->last) {
return NULL;
}
if(pos < 0 || pos >= mf->ixsize) {
return NULL;
}
x = pos - mf->last;
if(x < 0) {
x += (mf->ixsize - 1);
}
*size = mf->ix[x].size;
return &mf->buf[mf->ix[x].offset];
}
/**
* MFIFOGetMesCount
* \brief How many messages are currently in the buffer?
*/
int MFIFOGetMesCount(unsigned char *buf)
{
MFIFO *mf = (MFIFO *)buf;
if(mf->first == mf->last) {
return 0;
}
else if(mf->first > mf->last) {
return mf->first - mf->last;
}
else {
return (mf->ixsize - mf->last) + mf->first;
}
}
/**
* MFIFOWriteMesOverwrite
* \brief Same as MFIFOWriteMes but old frames will be overwritten if the fifo is full
*/
int MFIFOWriteMesOverwrite(unsigned char *buf, unsigned char *mes, int size)
{
MFIFO *mf = (MFIFO *)buf;
int of, ol, x;
x = mf->first + 1;
if(x >= mf->ixsize)
x = 0;
if(x == mf->last) {
/* advance last pointer */
mf->last++;
if(mf->last >= mf->ixsize)
mf->last = 0;
}
of = MFIFOGetFBOffset(buf);
ol = MFIFOGetLBOffset(buf);
if(mf->last == mf->first) /* empty queue */
{
mf->first = mf->last = 0; /* optimize */
MFIFOWriteIX(buf, mes, size, mf->first, 0);
return 1;
}
else if(of > ol)
{
if(mf->bsize - of >= size)
{
MFIFOWriteIX(buf, mes, size, mf->first, of);
return 1;
}
else if(ol > size)
{
MFIFOWriteIX(buf, mes, size, mf->first, ol);
return 1;
}
}
else if(ol - of > size)
{
MFIFOWriteIX(buf, mes, size, mf->first, of);
return 1;
}
return 0;
}

View File

@ -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.*/

View File

@ -155,12 +155,7 @@ L3INT nationalPmes_Setup(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT
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))

View File

@ -44,6 +44,10 @@
#define LINE "--------------------------------------------------------------------------------"
//#define IODEBUG
/* helper macros */
#define ZAP_SPAN_IS_BRI(x) ((x)->trunk_type == ZAP_TRUNK_BRI || (x)->trunk_type == ZAP_TRUNK_BRI_PTMP)
#define ZAP_SPAN_IS_NT(x) (((zap_isdn_data_t *)(x)->signal_data)->mode == Q921_NT)
static L2ULONG zap_time_now(void)
{
return (L2ULONG)zap_current_time_in_ms();
@ -67,91 +71,117 @@ static ZIO_CHANNEL_REQUEST_FUNCTION(isdn_channel_request)
Q931ie_CalledNum CalledNum;
Q931ie_CalledNum *ptrCalledNum;
Q931ie_Display Display, *ptrDisplay;
Q931ie_HLComp HLComp; /* High-Layer Compatibility IE */
Q931ie_SendComplete SComplete; /* Sending Complete IE */
Q931ie_ProgInd Progress; /* Progress Indicator IE */
zap_status_t status = ZAP_FAIL;
zap_isdn_data_t *isdn_data = span->signal_data;
int sanity = 60000;
int codec = 0;
Q931InitIEBearerCap(&BearerCap);
Q931InitIEChanID(&ChanID);
Q931InitIECallingNum(&CallingNum);
Q931InitIECalledNum(&CalledNum);
Q931InitIEDisplay(&Display);
/*
* get codec type
*/
zap_channel_command(&span->channels[chan_id], ZAP_COMMAND_GET_NATIVE_CODEC, &codec);
/*
* Q.931 Setup Message
*/
Q931InitMesGeneric(gen);
gen->MesType = Q931mes_SETUP;
gen->CRVFlag = 0; /* outgoing call */
BearerCap.CodStand = 0; /* ITU-T = 0, ISO/IEC = 1, National = 2, Network = 3 */
BearerCap.ITC = 0; /* Speech */
BearerCap.TransMode = 0; /* Circuit = 0, Packet = 1 */
BearerCap.ITR = 16; /* 64k */
/*
* Bearer Capability IE
*/
Q931InitIEBearerCap(&BearerCap);
BearerCap.CodStand = Q931_CODING_ITU; /* ITU-T = 0, ISO/IEC = 1, National = 2, Network = 3 */
BearerCap.ITC = Q931_ITC_SPEECH; /* Speech */
BearerCap.TransMode = 0; /* Circuit = 0, Packet = 1 */
BearerCap.ITR = Q931_ITR_64K; /* 64k */
BearerCap.Layer1Ident = 1;
BearerCap.UIL1Prot = 2; /* U-law (a-law = 3)*/
BearerCap.UIL1Prot = (codec == ZAP_CODEC_ALAW) ? Q931_UIL1P_G711A : Q931_UIL1P_G711U; /* U-law = 2, A-law = 3 */
gen->BearerCap = Q931AppendIE((L3UCHAR *) gen, (L3UCHAR *) &BearerCap);
ChanID.IntType = 1; /* PRI = 1, BRI = 0 */
ChanID.PrefExcl = (isdn_data->opts & ZAP_ISDN_OPT_SUGGEST_CHANNEL) ? 0 : 1; /* 0 = preferred, 1 exclusive */
ChanID.InfoChanSel = 1;
ChanID.ChanMapType = 3; /* B-Chan */
ChanID.ChanSlot = chan_id;
/*
* Channel ID IE
*/
Q931InitIEChanID(&ChanID);
ChanID.IntType = ZAP_SPAN_IS_BRI(span) ? 0 : 1; /* PRI = 1, BRI = 0 */
if(!ZAP_SPAN_IS_NT(span)) {
ChanID.PrefExcl = (isdn_data->opts & ZAP_ISDN_OPT_SUGGEST_CHANNEL) ? 0 : 1; /* 0 = preferred, 1 exclusive */
} else {
ChanID.PrefExcl = 1; /* always exclusive in NT-mode */
}
if(ChanID.IntType) {
ChanID.InfoChanSel = 1; /* None = 0, See Slot = 1, Any = 3 */
ChanID.ChanMapType = 3; /* B-Chan */
ChanID.ChanSlot = (unsigned char)chan_id;
} else {
ChanID.InfoChanSel = (unsigned char)chan_id & 0x03; /* None = 0, B1 = 1, B2 = 2, Any = 3 */
}
gen->ChanID = Q931AppendIE((L3UCHAR *) gen, (L3UCHAR *) &ChanID);
/*
* Progress IE
*/
Q931InitIEProgInd(&Progress);
Progress.CodStand = Q931_CODING_ITU; /* 0 = ITU */
Progress.Location = 0; /* 0 = User, 1 = Private Network */
Progress.ProgDesc = 3; /* 1 = Not end-to-end ISDN */
gen->ProgInd = Q931AppendIE((L3UCHAR *)gen, (L3UCHAR *)&Progress);
/*
* Display IE
*/
Q931InitIEDisplay(&Display);
Display.Size = Display.Size + (unsigned char)strlen(caller_data->cid_name);
gen->Display = Q931AppendIE((L3UCHAR *) gen, (L3UCHAR *) &Display);
ptrDisplay = Q931GetIEPtr(gen->Display, gen->buf);
zap_copy_string((char *)ptrDisplay->Display, caller_data->cid_name, strlen(caller_data->cid_name)+1);
/* TypNum: Type of number */
/* Bits 7 6 5 */
/* 000 Unknown */
/* 001 International number */
/* 010 National number */
/* 011 Network Specific number */
/* 100 Subscriber mumber */
/* 110 Abbreviated number */
/* 111 Reserved for extension */
/* All other values are reserved */
CallingNum.TypNum = 2;
/* NumPlanID */
/* Bits 4 3 2 1 */
/* 0000 Unknown */
/* 0001 ISDN/telephony numbering plan (E.164) */
/* 0011 Data numbering plan (X.121) */
/* 0100 Telex numbering plan (F.69) */
/* 1000 National standard numbering plan */
/* 1001 Private numbering plan */
/* 1111 Reserved for extension */
/* All other valures are reserved */
CallingNum.NumPlanID = 1;
/* Presentation indicator */
/* Bits 7 6 */
/* 00 Presenation Allowed */
/* 01 Presentation Restricted */
/* 10 Number not available due to internetworking */
/* 11 Reserved */
CallingNum.PresInd = 0;
/* Screening Indicator */
/* Bits 2 1 */
/* 00 User-provided, not screened */
/* 01 User-provided, verified and passed */
/* 10 User-provided, verified and failed */
/* 11 Network provided */
CallingNum.ScreenInd = 0;
/*
* Calling Number IE
*/
Q931InitIECallingNum(&CallingNum);
CallingNum.TypNum = Q931_TON_UNKNOWN;
CallingNum.NumPlanID = Q931_NUMPLAN_E164;
CallingNum.PresInd = Q931_PRES_ALLOWED;
CallingNum.ScreenInd = Q931_SCREEN_USER_NOT_SCREENED;
CallingNum.Size = CallingNum.Size + (unsigned char)strlen(caller_data->cid_num.digits);
gen->CallingNum = Q931AppendIE((L3UCHAR *) gen, (L3UCHAR *) &CallingNum);
ptrCallingNum = Q931GetIEPtr(gen->CallingNum, gen->buf);
zap_copy_string((char *)ptrCallingNum->Digit, caller_data->cid_num.digits, strlen(caller_data->cid_num.digits)+1);
CalledNum.TypNum = 2;
CalledNum.NumPlanID = 1;
/*
* Called number IE
*/
Q931InitIECalledNum(&CalledNum);
CalledNum.TypNum = Q931_TON_UNKNOWN;
CalledNum.NumPlanID = Q931_NUMPLAN_E164;
CalledNum.Size = CalledNum.Size + (unsigned char)strlen(caller_data->ani.digits);
gen->CalledNum = Q931AppendIE((L3UCHAR *) gen, (L3UCHAR *) &CalledNum);
ptrCalledNum = Q931GetIEPtr(gen->CalledNum, gen->buf);
zap_copy_string((char *)ptrCalledNum->Digit, caller_data->ani.digits, strlen(caller_data->ani.digits)+1);
/*
* High-Layer Compatibility IE (Note: Required for AVM FritzBox)
*/
Q931InitIEHLComp(&HLComp);
HLComp.CodStand = Q931_CODING_ITU; /* ITU */
HLComp.Interpret = 4; /* only possible value */
HLComp.PresMeth = 1; /* High-layer protocol profile */
HLComp.HLCharID = 1; /* Telephony = 1, Fax G2+3 = 4, Fax G4 = 65 (Class I)/ 68 (Class II or III) */
gen->HLComp = Q931AppendIE((L3UCHAR *) gen, (L3UCHAR *) &HLComp);
/*
* Sending complete IE (or some NT stuff waits forever in Q.931 overlap dial state...)
*/
SComplete.IEId = Q931ie_SENDING_COMPLETE;
// gen->SendComplete = Q931AppendIE((L3UCHAR *) gen, (L3UCHAR *) &SComplete);
caller_data->call_state = ZAP_CALLER_STATE_DIALING;
Q931Rx43(&isdn_data->q931, (L3UCHAR *) gen, gen->Size);
@ -211,7 +241,6 @@ static ZIO_CHANNEL_REQUEST_FUNCTION(isdn_channel_request)
case Q931mes_ALERTING:
new_chan->init_state = ZAP_CHANNEL_STATE_PROGRESS_MEDIA;
break;
break;
case Q931mes_CONNECT:
new_chan->init_state = ZAP_CHANNEL_STATE_UP;
break;
@ -275,13 +304,17 @@ static L3INT zap_isdn_931_34(void *pvt, L2UCHAR *msg, L2INT mlen)
if (Q931IsIEPresent(gen->ChanID)) {
Q931ie_ChanID *chanid = Q931GetIEPtr(gen->ChanID, gen->buf);
chan_id = chanid->ChanSlot;
if(chanid->IntType)
chan_id = chanid->ChanSlot;
else
chan_id = chanid->InfoChanSel;
}
assert(span != NULL);
assert(isdn_data != NULL);
zap_log(ZAP_LOG_DEBUG, "Yay I got an event! Type:[%02x] Size:[%d]\n", gen->MesType, gen->Size);
zap_log(ZAP_LOG_DEBUG, "Yay I got an event! Type:[%02x] Size:[%d] CRV: %d (%#hx, CTX: %s)\n", gen->MesType, gen->Size, gen->CRV, gen->CRV, gen->CRVFlag ? "Terminator" : "Originator");
if (gen->CRVFlag && (caller_data = isdn_data->outbound_crv[gen->CRV])) {
if (chan_id) {
@ -313,7 +346,7 @@ static L3INT zap_isdn_931_34(void *pvt, L2UCHAR *msg, L2INT mlen)
zchan = isdn_data->channels_remote_crv[gen->CRV];
}
zap_log(ZAP_LOG_DEBUG, "zchan %x source isdn_data->channels_%s_crv[%#hx]\n", zchan, gen->CRVFlag ? "local" : "remote", gen->CRV);
if (gen->ProtDisc == 3) {
@ -376,8 +409,34 @@ static L3INT zap_isdn_931_34(void *pvt, L2UCHAR *msg, L2INT mlen)
const char *what = gen->MesType == Q931mes_RELEASE ? "Release" : "Release Complete";
if (zchan) {
if (zchan->state == ZAP_CHANNEL_STATE_TERMINATING || zchan->state == ZAP_CHANNEL_STATE_HANGUP) {
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_HANGUP_COMPLETE);
} else {
if (gen->MesType == Q931mes_RELEASE) {
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_HANGUP_COMPLETE);
} else {
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_DOWN);
}
}
else if((gen->MesType == Q931mes_RELEASE && zchan->state <= ZAP_CHANNEL_STATE_UP) ||
(gen->MesType == Q931mes_RELEASE_COMPLETE && zchan->state == ZAP_CHANNEL_STATE_DIALING)) {
/*
* Don't keep inbound channels open if the remote side hangs up before we answered
*/
Q931ie_Cause *cause = Q931GetIEPtr(gen->Cause, gen->buf);
zap_sigmsg_t sig;
zap_status_t status;
memset(&sig, 0, sizeof(sig));
sig.chan_id = zchan->chan_id;
sig.span_id = zchan->span_id;
sig.channel = zchan;
sig.channel->caller_data.hangup_cause = (cause) ? cause->Value : ZAP_CAUSE_NORMAL_UNSPECIFIED;
sig.event_id = ZAP_SIGEVENT_STOP;
status = isdn_data->sig_cb(&sig);
zap_log(ZAP_LOG_DEBUG, "Received %s in state %s, requested hangup for channel %d:%d\n", what, zap_channel_state2str(zchan->state), zchan->span_id, chan_id);
}
else {
zap_log(ZAP_LOG_DEBUG, "Ignoring %s on channel %d\n", what, chan_id);
}
} else {
@ -418,6 +477,10 @@ static L3INT zap_isdn_931_34(void *pvt, L2UCHAR *msg, L2INT mlen)
{
if (zchan) {
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_UP);
gen->MesType = Q931mes_CONNECT_ACKNOWLEDGE;
gen->CRVFlag = 0; /* outbound */
Q931Rx43(&isdn_data->q931, (L3UCHAR *) gen, gen->Size);
} else {
zap_log(ZAP_LOG_CRIT, "Received Connect with no matching channel %d\n", chan_id);
}
@ -425,23 +488,35 @@ static L3INT zap_isdn_931_34(void *pvt, L2UCHAR *msg, L2INT mlen)
break;
case Q931mes_SETUP:
{
Q931ie_CallingNum *callingnum = Q931GetIEPtr(gen->CallingNum, gen->buf);
Q931ie_CalledNum *callednum = Q931GetIEPtr(gen->CalledNum, gen->buf);
zap_status_t status;
int fail = 1;
uint32_t cplen = mlen;
if(zchan && zchan == isdn_data->channels_remote_crv[gen->CRV]) {
zap_log(ZAP_LOG_INFO, "Duplicate SETUP message(?) for Channel %d:%d ~ %d:%d in state %s [ignoring]\n",
zchan->span_id,
zchan->chan_id,
zchan->physical_span_id,
zchan->physical_chan_id,
zap_channel_state2str(zchan->state));
break;
}
zchan = NULL;
if (chan_id < ZAP_MAX_CHANNELS_SPAN && chan_id <= span->chan_count) {
zchan = &span->channels[chan_id];
}
if (zchan && (status = zap_channel_open_chan(zchan) == ZAP_SUCCESS)) {
if (zchan) {
if (zap_test_flag(zchan, ZAP_CHANNEL_INUSE) || zchan->state != ZAP_CHANNEL_STATE_DOWN) {
if (zchan->state == ZAP_CHANNEL_STATE_DOWN || zchan->state >= ZAP_CHANNEL_STATE_TERMINATING) {
int x = 0;
zap_log(ZAP_LOG_WARNING, "Channel %d:%d ~ %d:%d is already in use waiting for it to become available.\n");
zap_log(ZAP_LOG_WARNING, "Channel %d:%d ~ %d:%d is already in use waiting for it to become available.\n",
zchan->span_id,
zchan->chan_id,
zchan->physical_span_id,
zchan->physical_chan_id);
for (x = 0; x < 200; x++) {
if (!zap_test_flag(zchan, ZAP_CHANNEL_INUSE)) {
@ -485,9 +560,10 @@ static L3INT zap_isdn_931_34(void *pvt, L2UCHAR *msg, L2INT mlen)
if (fail) {
Q931ie_Cause cause;
gen->MesType = Q931mes_DISCONNECT;
gen->CRVFlag = 1; /* inbound call */
cause.IEId = Q931ie_CAUSE;
cause.Size = sizeof(Q931ie_Cause);
cause.CodStand = 0;
cause.CodStand = Q931_CODING_ITU;
cause.Location = 1;
cause.Recom = 1;
//should we be casting here.. or do we need to translate value?
@ -506,11 +582,35 @@ static L3INT zap_isdn_931_34(void *pvt, L2UCHAR *msg, L2INT mlen)
zap_log(ZAP_LOG_CRIT, "Failed to open channel for new setup message\n");
}
} else {
Q931ie_ProgInd progress;
/*
* Setup Progress indicator
*/
progress.IEId = Q931ie_PROGRESS_INDICATOR;
progress.Size = sizeof(Q931ie_ProgInd);
progress.CodStand = Q931_CODING_ITU; /* ITU */
progress.Location = 1; /* private network serving the local user */
progress.ProgDesc = 1; /* call is not end-to-end isdn = 1, in-band information available = 8 */
gen->ProgInd = Q931AppendIE((L3UCHAR *) gen, (L3UCHAR *) &progress);
}
}
break;
case Q931mes_CALL_PROCEEDING:
{
if (zchan) {
zap_log(ZAP_LOG_CRIT, "Received CALL PROCEEDING message for channel %d\n", chan_id);
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_PROGRESS);
} else {
zap_log(ZAP_LOG_CRIT, "Received CALL PROCEEDING with no matching channel %d\n", chan_id);
}
}
break;
default:
zap_log(ZAP_LOG_CRIT, "Received unhandled message %d (%#x)\n", (int)gen->MesType, (int)gen->MesType);
break;
}
}
@ -518,16 +618,23 @@ static L3INT zap_isdn_931_34(void *pvt, L2UCHAR *msg, L2INT mlen)
return 0;
}
static int zap_isdn_921_23(void *pvt, L2UCHAR *msg, L2INT mlen)
static int zap_isdn_921_23(void *pvt, Q921DLMsg_t ind, L2UCHAR tei, L2UCHAR *msg, L2INT mlen)
{
int ret;
int ret, offset = (ind == Q921_DL_DATA) ? 4 : 3;
char bb[4096] = "";
print_hex_bytes(msg+4, mlen-2, bb, sizeof(bb));
zap_log(ZAP_LOG_DEBUG, "READ %d\n%s\n%s\n\n", (int)mlen-2, LINE, bb);
ret = Q931Rx23(pvt, msg, mlen);
if (ret != 0)
zap_log(ZAP_LOG_DEBUG, "931 parse error [%d] [%s]\n", ret, q931_error_to_name(ret));
switch(ind) {
case Q921_DL_DATA:
case Q921_DL_UNIT_DATA:
print_hex_bytes(msg + offset, mlen - offset, bb, sizeof(bb));
zap_log(ZAP_LOG_DEBUG, "READ %d\n%s\n%s\n\n", (int)mlen - offset, LINE, bb);
default:
ret = Q931Rx23(pvt, ind, tei, msg, mlen);
if (ret != 0)
zap_log(ZAP_LOG_DEBUG, "931 parse error [%d] [%s]\n", ret, q931_error_to_name(ret));
break;
}
return ((ret >= 0) ? 1 : 0);
}
@ -568,6 +675,11 @@ static __inline__ void state_advance(zap_channel_t *zchan)
case ZAP_CHANNEL_STATE_DOWN:
{
if (gen->CRV) {
if(gen->CRVFlag) {
isdn_data->channels_local_crv[gen->CRV] = NULL;
} else {
isdn_data->channels_remote_crv[gen->CRV] = NULL;
}
Q931ReleaseCRV(&isdn_data->q931, gen->CRV);
}
zap_channel_done(zchan);
@ -582,6 +694,8 @@ static __inline__ void state_advance(zap_channel_t *zchan)
}
} else {
gen->MesType = Q931mes_CALL_PROCEEDING;
gen->CRVFlag = 1; /* inbound */
Q931Rx43(&isdn_data->q931, (void *)gen, gen->Size);
}
}
@ -594,7 +708,6 @@ static __inline__ void state_advance(zap_channel_t *zchan)
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_HANGUP);
}
}
}
break;
case ZAP_CHANNEL_STATE_RESTART:
@ -613,7 +726,14 @@ static __inline__ void state_advance(zap_channel_t *zchan)
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_HANGUP);
}
} else {
if (!zap_test_flag(zchan, ZAP_CHANNEL_OPEN)) {
if (zap_channel_open_chan(zchan) != ZAP_SUCCESS) {
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_HANGUP);
return;
}
}
gen->MesType = Q931mes_ALERTING;
gen->CRVFlag = 1; /* inbound call */
Q931Rx43(&isdn_data->q931, (void *)gen, gen->Size);
}
}
@ -626,8 +746,15 @@ static __inline__ void state_advance(zap_channel_t *zchan)
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_HANGUP);
}
} else {
if (!zap_test_flag(zchan, ZAP_CHANNEL_OPEN)) {
if (zap_channel_open_chan(zchan) != ZAP_SUCCESS) {
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_HANGUP);
return;
}
}
gen->MesType = Q931mes_CONNECT;
gen->BearerCap = 0;
gen->CRVFlag = 1; /* inbound call */
Q931Rx43(&isdn_data->q931, (void *)gen, zchan->caller_data.raw_data_len);
}
}
@ -641,117 +768,193 @@ static __inline__ void state_advance(zap_channel_t *zchan)
Q931ie_CalledNum CalledNum;
Q931ie_CalledNum *ptrCalledNum;
Q931ie_Display Display, *ptrDisplay;
Q931InitIEBearerCap(&BearerCap);
Q931InitIEChanID(&ChanID);
Q931InitIECallingNum(&CallingNum);
Q931InitIECalledNum(&CalledNum);
Q931InitIEDisplay(&Display);
Q931ie_HLComp HLComp; /* High-Layer Compatibility IE */
Q931ie_SendComplete SComplete; /* Sending Complete IE */
Q931ie_ProgInd Progress; /* Progress Indicator IE */
int codec = 0;
/*
* get codec type
*/
zap_channel_command(&zchan->span->channels[zchan->chan_id], ZAP_COMMAND_GET_NATIVE_CODEC, &codec);
/*
* Q.931 Setup Message
*/
Q931InitMesGeneric(gen);
gen->MesType = Q931mes_SETUP;
gen->CRVFlag = 0; /* outbound(?) */
BearerCap.CodStand = 0; /* ITU-T = 0, ISO/IEC = 1, National = 2, Network = 3 */
BearerCap.ITC = 0; /* Speech */
BearerCap.TransMode = 0; /* Circuit = 0, Packet = 1 */
BearerCap.ITR = 16; /* 64k */
/*
* Bearer Capability IE
*/
Q931InitIEBearerCap(&BearerCap);
BearerCap.CodStand = Q931_CODING_ITU; /* ITU-T = 0, ISO/IEC = 1, National = 2, Network = 3 */
BearerCap.ITC = Q931_ITC_SPEECH; /* Speech */
BearerCap.TransMode = 0; /* Circuit = 0, Packet = 1 */
BearerCap.ITR = Q931_ITR_64K; /* 64k = 16, Packet mode = 0 */
BearerCap.Layer1Ident = 1;
BearerCap.UIL1Prot = 2; /* U-law (a-law = 3)*/
BearerCap.UIL1Prot = (codec == ZAP_CODEC_ALAW) ? 3 : 2; /* U-law = 2, A-law = 3 */
gen->BearerCap = Q931AppendIE((L3UCHAR *) gen, (L3UCHAR *) &BearerCap);
//is cast right here?
ChanID.IntType = 1; /* PRI = 1, BRI = 0 */
ChanID.InfoChanSel = 1;
ChanID.ChanMapType = 3; /* B-Chan */
ChanID.ChanSlot = (unsigned char)zchan->chan_id;
/*
* ChannelID IE
*/
Q931InitIEChanID(&ChanID);
ChanID.IntType = ZAP_SPAN_IS_BRI(zchan->span) ? 0 : 1; /* PRI = 1, BRI = 0 */
ChanID.PrefExcl = ZAP_SPAN_IS_NT(zchan->span) ? 1 : 0; /* Exclusive in NT-mode = 1, Preferred otherwise = 0 */
if(ChanID.IntType) {
ChanID.InfoChanSel = 1; /* None = 0, See Slot = 1, Any = 3 */
ChanID.ChanMapType = 3; /* B-Chan */
ChanID.ChanSlot = (unsigned char)zchan->chan_id;
} else {
ChanID.InfoChanSel = (unsigned char)zchan->chan_id & 0x03; /* None = 0, B1 = 1, B2 = 2, Any = 3 */
}
gen->ChanID = Q931AppendIE((L3UCHAR *) gen, (L3UCHAR *) &ChanID);
/*
* Progress IE
*/
Q931InitIEProgInd(&Progress);
Progress.CodStand = Q931_CODING_ITU; /* 0 = ITU */
Progress.Location = 0; /* 0 = User, 1 = Private Network */
Progress.ProgDesc = 3; /* 1 = Not end-to-end ISDN */
gen->ProgInd = Q931AppendIE((L3UCHAR *)gen, (L3UCHAR *)&Progress);
/*
* Display IE
*/
Q931InitIEDisplay(&Display);
Display.Size = Display.Size + (unsigned char)strlen(zchan->caller_data.cid_name);
gen->Display = Q931AppendIE((L3UCHAR *) gen, (L3UCHAR *) &Display);
ptrDisplay = Q931GetIEPtr(gen->Display, gen->buf);
zap_copy_string((char *)ptrDisplay->Display, zchan->caller_data.cid_name, strlen(zchan->caller_data.cid_name)+1);
/* TypNum: Type of number*/
/* Bits 7 6 5*/
/* 000Unknown*/
/* 001International number*/
/* 010National number*/
/* 011Network Specific number */
/* 100Subscriber mumber*/
/* 110Abbreviated number*/
/* 111Reserved for extension*/
/* All other values are reserved */
CallingNum.TypNum = 2;
/* NumPlanID*/
/* Bits 4 3 2 1*/
/* 0000Unknown*/
/* 0001ISDN/telephony numbering plan (E.164)*/
/* 0011Data numbering plan (X.121)*/
/* 0100Telex numbering plan (F.69)*/
/* 1000National standard numbering plan*/
/* 1001Private numbering plan*/
/* 1111Reserved for extension*/
/* All other valures are reserved*/
CallingNum.NumPlanID = 1;
/* Presentation indicator*/
/* Bits 7 6*/
/* 00Presenation Allowed*/
/* 01Presentation Restricted*/
/* 10Number not available due to internetworking*/
/* 11Reserved*/
CallingNum.PresInd = 0;
/* Screening Indicator*/
/* Bits 2 1*/
/* 00User-provided, not screened*/
/* 01User-provided, verified and passed*/
/* 10User-provided, verified and failed*/
/* 11Network provided*/
CallingNum.ScreenInd = 0;
/*
* CallingNum IE
*/
Q931InitIECallingNum(&CallingNum);
CallingNum.TypNum = Q931_TON_UNKNOWN;
CallingNum.NumPlanID = Q931_NUMPLAN_E164;
CallingNum.PresInd = Q931_PRES_ALLOWED;
CallingNum.ScreenInd = Q931_SCREEN_USER_NOT_SCREENED;
CallingNum.Size = CallingNum.Size + (unsigned char)strlen(zchan->caller_data.cid_num.digits);
gen->CallingNum = Q931AppendIE((L3UCHAR *) gen, (L3UCHAR *) &CallingNum);
ptrCallingNum = Q931GetIEPtr(gen->CallingNum, gen->buf);
zap_copy_string((char *)ptrCallingNum->Digit, zchan->caller_data.cid_num.digits, strlen(zchan->caller_data.cid_num.digits)+1);
CalledNum.TypNum = 2;
CalledNum.NumPlanID = 1;
/*
* CalledNum IE
*/
Q931InitIECalledNum(&CalledNum);
CalledNum.TypNum = Q931_TON_UNKNOWN;
CalledNum.NumPlanID = Q931_NUMPLAN_E164;
CalledNum.Size = CalledNum.Size + (unsigned char)strlen(zchan->caller_data.ani.digits);
gen->CalledNum = Q931AppendIE((L3UCHAR *) gen, (L3UCHAR *) &CalledNum);
ptrCalledNum = Q931GetIEPtr(gen->CalledNum, gen->buf);
zap_copy_string((char *)ptrCalledNum->Digit, zchan->caller_data.ani.digits, strlen(zchan->caller_data.ani.digits)+1);
/*
* High-Layer Compatibility IE (Note: Required for AVM FritzBox)
*/
Q931InitIEHLComp(&HLComp);
HLComp.CodStand = Q931_CODING_ITU; /* ITU */
HLComp.Interpret = 4; /* only possible value */
HLComp.PresMeth = 1; /* High-layer protocol profile */
HLComp.HLCharID = Q931_HLCHAR_TELEPHONY; /* Telephony = 1, Fax G2+3 = 4, Fax G4 = 65 (Class I)/ 68 (Class II or III) */ /* TODO: make accessible from user layer */
gen->HLComp = Q931AppendIE((L3UCHAR *) gen, (L3UCHAR *) &HLComp);
/*
* Sending complete IE (or some NT stuff waits forever in Q.931 overlap dial state...)
*/
SComplete.IEId = Q931ie_SENDING_COMPLETE;
// gen->SendComplete = Q931AppendIE((L3UCHAR *) gen, (L3UCHAR *) &SComplete);
Q931Rx43(&isdn_data->q931, (L3UCHAR *) gen, gen->Size);
isdn_data->channels_local_crv[gen->CRV] = zchan;
}
break;
case ZAP_CHANNEL_STATE_HANGUP_COMPLETE:
{
/* reply RELEASE with RELEASE_COMPLETE message */
if(zchan->last_state == ZAP_CHANNEL_STATE_HANGUP) {
gen->MesType = Q931mes_RELEASE_COMPLETE;
Q931Rx43(&isdn_data->q931, (L3UCHAR *) gen, gen->Size);
}
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_DOWN);
}
break;
case ZAP_CHANNEL_STATE_HANGUP:
{
Q931ie_Cause cause;
gen->MesType = Q931mes_DISCONNECT;
zap_log(ZAP_LOG_DEBUG, "Hangup: Direction %s\n", zap_test_flag(zchan, ZAP_CHANNEL_OUTBOUND) ? "Outbound" : "Inbound");
gen->CRVFlag = zap_test_flag(zchan, ZAP_CHANNEL_OUTBOUND) ? 0 : 1;
cause.IEId = Q931ie_CAUSE;
cause.Size = sizeof(Q931ie_Cause);
cause.CodStand = 0;
cause.Location = 1;
cause.Recom = 1;
//should we be casting here.. or do we need to translate value?
cause.Value = (unsigned char) zchan->caller_data.hangup_cause;
*cause.Diag = '\0';
gen->Cause = Q931AppendIE((L3UCHAR *) gen, (L3UCHAR *) &cause);
Q931Rx43(&isdn_data->q931, (L3UCHAR *) gen, gen->Size);
cause.CodStand = Q931_CODING_ITU; /* ITU */
cause.Location = 1; /* private network */
cause.Recom = 1; /* */
/*
* BRI PTMP needs special handling here...
* TODO: cleanup / refine (see above)
*/
if (zchan->last_state == ZAP_CHANNEL_STATE_RING) {
/*
* inbound call [was: number unknown (= not found in routing state)]
* (in Q.931 spec terms: Reject request)
*/
gen->MesType = Q931mes_RELEASE_COMPLETE;
//cause.Value = (unsigned char) ZAP_CAUSE_UNALLOCATED;
cause.Value = (unsigned char) zchan->caller_data.hangup_cause;
*cause.Diag = '\0';
gen->Cause = Q931AppendIE((L3UCHAR *) gen, (L3UCHAR *) &cause);
Q931Rx43(&isdn_data->q931, (L3UCHAR *) gen, gen->Size);
/* we're done, release channel */
//zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_HANGUP_COMPLETE);
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_DOWN);
}
else if (zchan->last_state <= ZAP_CHANNEL_STATE_PROGRESS) {
/*
* just release all unanswered calls [was: inbound call, remote side hung up before we answered]
*/
gen->MesType = Q931mes_RELEASE;
cause.Value = (unsigned char) zchan->caller_data.hangup_cause;
*cause.Diag = '\0';
gen->Cause = Q931AppendIE((L3UCHAR *) gen, (L3UCHAR *) &cause);
Q931Rx43(&isdn_data->q931, (void *)gen, gen->Size);
/* this will be triggered by the RELEASE_COMPLETE reply */
/* zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_HANGUP_COMPLETE); */
}
else {
/*
* call connected, hangup
*/
gen->MesType = Q931mes_DISCONNECT;
cause.Value = (unsigned char) zchan->caller_data.hangup_cause;
*cause.Diag = '\0';
gen->Cause = Q931AppendIE((L3UCHAR *) gen, (L3UCHAR *) &cause);
Q931Rx43(&isdn_data->q931, (L3UCHAR *) gen, gen->Size);
}
}
break;
case ZAP_CHANNEL_STATE_TERMINATING:
{
zap_log(ZAP_LOG_DEBUG, "Terminating: Direction %s\n", zap_test_flag(zchan, ZAP_CHANNEL_OUTBOUND) ? "Outbound" : "Inbound");
sig.event_id = ZAP_SIGEVENT_STOP;
status = isdn_data->sig_cb(&sig);
gen->MesType = Q931mes_RELEASE;
gen->CRVFlag = zap_test_flag(zchan, ZAP_CHANNEL_OUTBOUND) ? 0 : 1;
Q931Rx43(&isdn_data->q931, (void *)gen, gen->Size);
}
default:
@ -871,6 +1074,7 @@ static void *zap_isdn_run(zap_thread_t *me, void *obj)
zap_status_t status = zap_channel_wait(isdn_data->dchan, &flags, 100);
Q921TimerTick(&isdn_data->q921);
Q931TimerTick(&isdn_data->q931);
check_state(span);
check_events(span);
@ -887,8 +1091,6 @@ static void *zap_isdn_run(zap_thread_t *me, void *obj)
break;
case ZAP_TIMEOUT:
{
/*zap_log(ZAP_LOG_DEBUG, "Timeout!\n");*/
/*Q931TimeTick(isdn_data->q931, L3ULONG ms);*/
errs = 0;
}
break;
@ -937,7 +1139,8 @@ zap_status_t zap_isdn_init(void)
Q931Initialize();
Q921SetGetTimeCB(zap_time_now);
Q931SetGetTimeCB(zap_time_now);
return ZAP_SUCCESS;
}
@ -948,16 +1151,66 @@ zap_status_t zap_isdn_start(zap_span_t *span)
return zap_thread_create_detached(zap_isdn_run, span);
}
static int q931_rx_32(void *pvt,L3UCHAR *msg, L3INT mlen)
static int q931_rx_32(void *pvt, Q921DLMsg_t ind, L3UCHAR tei, L3UCHAR *msg, L3INT mlen)
{
int ret;
int offset = 4;
char bb[4096] = "";
ret = Q921Rx32(pvt, msg, mlen);
print_hex_bytes(msg, mlen, bb, sizeof(bb));
zap_log(ZAP_LOG_DEBUG, "WRITE %d\n%s\n%s\n\n", (int)mlen, LINE, bb);
return ret;
switch(ind) {
case Q921_DL_UNIT_DATA:
offset = 3;
case Q921_DL_DATA:
print_hex_bytes(msg + offset, mlen - offset, bb, sizeof(bb));
zap_log(ZAP_LOG_DEBUG, "WRITE %d\n%s\n%s\n\n", (int)mlen - offset, LINE, bb);
break;
default:
break;
}
return Q921Rx32(pvt, ind, tei, msg, mlen);
}
static int zap_isdn_q921_log(void *pvt, Q921LogLevel_t level, char *msg, L2INT size)
{
int loglevel = ZAP_LOG_LEVEL_DEBUG;
switch(level) {
case Q921_LOG_DEBUG:
loglevel = ZAP_LOG_LEVEL_DEBUG;
break;
case Q921_LOG_INFO:
loglevel = ZAP_LOG_LEVEL_INFO;
break;
case Q921_LOG_NOTICE:
loglevel = ZAP_LOG_LEVEL_NOTICE;
break;
case Q921_LOG_WARNING:
loglevel = ZAP_LOG_LEVEL_WARNING;
break;
case Q921_LOG_ERROR:
loglevel = ZAP_LOG_LEVEL_ERROR;
break;
default:
return 0;
}
zap_log(__FILE__, "Q.921", __LINE__, loglevel, "%s", msg);
return 0;
}
static L3INT zap_isdn_q931_log(void *pvt, Q931LogLevel_t level, char *msg, L3INT size)
{
zap_log(__FILE__, "Q.931", __LINE__, ZAP_LOG_LEVEL_DEBUG, "%s", msg);
return 0;
}
static zap_state_map_t isdn_state_map = {
{
@ -995,7 +1248,7 @@ static zap_state_map_t isdn_state_map = {
ZSD_OUTBOUND,
ZSM_UNACCEPTABLE,
{ZAP_CHANNEL_STATE_HANGUP, ZAP_CHANNEL_STATE_TERMINATING, ZAP_END},
{ZAP_CHANNEL_STATE_HANGUP_COMPLETE, ZAP_END}
{ZAP_CHANNEL_STATE_HANGUP_COMPLETE, ZAP_CHANNEL_STATE_DOWN, ZAP_END}
},
{
ZSD_OUTBOUND,
@ -1039,7 +1292,7 @@ static zap_state_map_t isdn_state_map = {
ZSD_INBOUND,
ZSM_UNACCEPTABLE,
{ZAP_CHANNEL_STATE_HANGUP, ZAP_CHANNEL_STATE_TERMINATING, ZAP_END},
{ZAP_CHANNEL_STATE_HANGUP_COMPLETE, ZAP_END},
{ZAP_CHANNEL_STATE_HANGUP_COMPLETE, ZAP_CHANNEL_STATE_DOWN, ZAP_END},
},
{
ZSD_INBOUND,
@ -1108,29 +1361,38 @@ zap_status_t zap_isdn_configure_span(zap_span_t *span, Q921NetUser_t mode, Q931D
isdn_data->dchans[0] = dchans[0];
isdn_data->dchans[1] = dchans[1];
isdn_data->dchan = isdn_data->dchans[0];
isdn_data->mode = mode;
Q921_InitTrunk(&isdn_data->q921,
0,
0,
mode,
span->trunk_type == ZAP_TRUNK_BRI_PTMP ? Q921_PTMP : Q921_PTP,
0,
zap_isdn_921_21,
(Q921TxCB_t)zap_isdn_921_23,
(Q921Tx23CB_t)zap_isdn_921_23,
span,
&isdn_data->q931);
Q921SetLogCB(&isdn_data->q921, &zap_isdn_q921_log, isdn_data);
Q921SetLogLevel(&isdn_data->q921, Q921_LOG_DEBUG);
Q931Api_InitTrunk(&isdn_data->q931,
dialect,
mode,
span->trunk_type,
zap_isdn_931_34,
(Q931TxCB_t)q931_rx_32,
(Q931Tx32CB_t)q931_rx_32,
zap_isdn_931_err,
&isdn_data->q921,
span);
Q931SetLogCB(&isdn_data->q931, &zap_isdn_q931_log, isdn_data);
Q931SetLogLevel(&isdn_data->q931, Q931_LOG_DEBUG);
isdn_data->q931.autoRestartAck = 1;
isdn_data->q931.autoConnectAck = 1;
// isdn_data->q931.autoConnectAck = 1;
isdn_data->q931.autoConnectAck = 0;
isdn_data->q931.autoServiceAck = 1;
span->signal_data = isdn_data;
span->signal_type = ZAP_SIGTYPE_ISDN;