362 lines
12 KiB
C
362 lines
12 KiB
C
/*****************************************************************************
|
|
|
|
FileName: 5ESSmes.c
|
|
|
|
Contents: Pack/Unpack functions. These functions will unpack a 5ESS ISDN
|
|
message from the bit packed original format into structs
|
|
that contains variables sized by the user. It will also pack
|
|
the struct back into a Q.931 message as required.
|
|
|
|
See 5ESS.h for description.
|
|
|
|
License/Copyright:
|
|
|
|
Copyright (c) 2007, Jan Vidar Berger, Case Labs, Ltd. All rights reserved.
|
|
email:janvb@caselaboratories.com
|
|
|
|
Copyright (c) 2007, Michael Jerris. All rights reserved.
|
|
email:mike@jerris.com
|
|
|
|
Copyright (c) 2007, Michael S. Collins, All rights reserved.
|
|
email:mcollins@fcnetwork.com
|
|
|
|
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.
|
|
|
|
*****************************************************************************/
|
|
|
|
#include "5ESS.h"
|
|
|
|
/*****************************************************************************
|
|
|
|
Function: ATT5ESSUmes_Setup
|
|
|
|
*****************************************************************************/
|
|
L3INT ATT5ESSUmes_Setup(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size)
|
|
{
|
|
L3INT ir = 0;
|
|
L3INT OOff = 0;
|
|
L3INT rc = Q931E_NO_ERROR;
|
|
L3UCHAR last_codeset = 0, codeset = 0;
|
|
L3UCHAR shift_nolock = 1;
|
|
|
|
while (IOff < Size) {
|
|
|
|
if (shift_nolock) {
|
|
codeset = last_codeset;
|
|
}
|
|
|
|
if ((IBuf[IOff] & 0xF0) == Q931ie_SHIFT) {
|
|
shift_nolock = (IBuf[IOff] & 0x08);
|
|
if (shift_nolock) {
|
|
last_codeset = codeset;
|
|
}
|
|
codeset = ((IBuf[IOff] & 0x07));
|
|
IOff++;
|
|
}
|
|
|
|
if (codeset == 0) {
|
|
switch (IBuf[IOff])
|
|
{
|
|
case Q931ie_SENDING_COMPLETE:
|
|
case Q931ie_BEARER_CAPABILITY:
|
|
case Q931ie_CHANNEL_IDENTIFICATION:
|
|
case Q931ie_PROGRESS_INDICATOR:
|
|
case Q931ie_NETWORK_SPECIFIC_FACILITIES:
|
|
case Q931ie_DISPLAY:
|
|
case Q931ie_DATETIME:
|
|
case Q931ie_KEYPAD_FACILITY:
|
|
case Q931ie_SIGNAL:
|
|
case Q931ie_CALLING_PARTY_NUMBER:
|
|
case Q931ie_CALLING_PARTY_SUBADDRESS:
|
|
case Q931ie_CALLED_PARTY_NUMBER:
|
|
case Q931ie_CALLED_PARTY_SUBADDRESS:
|
|
case Q931ie_TRANSIT_NETWORK_SELECTION:
|
|
case Q931ie_LOW_LAYER_COMPATIBILITY:
|
|
case Q931ie_HIGH_LAYER_COMPATIBILITY:
|
|
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;
|
|
break;
|
|
case Q931ie_REPEAT_INDICATOR:
|
|
if (ir < 2) {
|
|
rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff);
|
|
ir++;
|
|
} else {
|
|
return Q931E_ILLEGAL_IE;
|
|
}
|
|
break;
|
|
default:
|
|
return Q931E_ILLEGAL_IE;
|
|
break;
|
|
}
|
|
} else if (codeset == 6) {
|
|
switch (IBuf[IOff])
|
|
{
|
|
case Q931ie_GENERIC_DIGITS:
|
|
rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff);
|
|
if (rc != Q931E_NO_ERROR)
|
|
return rc;
|
|
break;
|
|
default:
|
|
return Q931E_ILLEGAL_IE;
|
|
break;
|
|
}
|
|
} else if (codeset == 7) {
|
|
switch (IBuf[IOff])
|
|
{
|
|
case Q931ie_DISPLAY:
|
|
rc = Q931Uie[pTrunk->Dialect][IBuf[IOff]](pTrunk, mes, &IBuf[IOff], &mes->buf[OOff], &IOff, &OOff);
|
|
if (rc != Q931E_NO_ERROR)
|
|
return rc;
|
|
break;
|
|
default:
|
|
return Q931E_ILLEGAL_IE;
|
|
break;
|
|
}
|
|
} else {
|
|
return Q931E_ILLEGAL_IE;
|
|
}
|
|
}
|
|
mes->Size = sizeof(Q931mes_Generic) - 1 + OOff;
|
|
return Q931E_NO_ERROR;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
|
|
Function: ATT5ESSPmes_Setup
|
|
|
|
Decription: Pack a Q931mes_Generic into a real Q.931 message. The user will
|
|
set up a SETUP message and issue this to the stack where it
|
|
is processed by Q931ProcSetup that processes and validates
|
|
it before it actually sends it out. This function is called
|
|
to compute the real Q.931 message.
|
|
|
|
Parameters: IBuf[IN] Ptr to un-packed struct
|
|
ISize[IN] Size of input buffer (unpacked message).
|
|
OBuf[OUT] Ptr to packed 'octet' wise message.
|
|
OSize[OUT] Size of packed message.
|
|
|
|
Called By: Q931ProcSetup
|
|
|
|
*****************************************************************************/
|
|
L3INT ATT5ESSPmes_Setup(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;
|
|
|
|
/* Q931 Message Header */
|
|
Q931MesgHeader(pTrunk, pMes, OBuf, *OSize, &Octet);
|
|
|
|
/* Sending Complete */
|
|
if (Q931IsIEPresent(pMes->SendComplete)) {
|
|
OBuf[Octet++] = (L3UCHAR)(pMes->SendComplete & 0x00ff);
|
|
}
|
|
|
|
/* Repeat Indicator */
|
|
if (Q931IsIEPresent(pMes->RepeatInd)) {
|
|
OBuf[Octet++] = (L3UCHAR)(pMes->RepeatInd & 0x00ff);
|
|
}
|
|
|
|
/* Bearer capability */
|
|
if (Q931IsIEPresent(pMes->BearerCap)) {
|
|
if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_BEARER_CAPABILITY](pTrunk, Q931GetIEPtr(pMes->BearerCap,pMes->buf), OBuf, &Octet))!=0)
|
|
return rc;
|
|
} else {
|
|
rc = Q931E_BEARERCAP;
|
|
}
|
|
|
|
/* Channel Identification */
|
|
if (Q931IsIEPresent(pMes->ChanID)) {
|
|
if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CHANNEL_IDENTIFICATION](pTrunk, Q931GetIEPtr(pMes->ChanID,pMes->buf), OBuf, &Octet))!=0)
|
|
return rc;
|
|
}
|
|
|
|
/* Progress indicator */
|
|
if (Q931IsIEPresent(pMes->ProgInd)) {
|
|
if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_PROGRESS_INDICATOR](pTrunk, Q931GetIEPtr(pMes->ProgInd,pMes->buf), OBuf, &Octet))!=0)
|
|
return rc;
|
|
}
|
|
|
|
/* Network specific facilities */
|
|
if (Q931IsIEPresent(pMes->NetFac)) {
|
|
if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_NETWORK_SPECIFIC_FACILITIES](pTrunk, Q931GetIEPtr(pMes->NetFac,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;
|
|
}
|
|
|
|
/* Date/Time */
|
|
if (Q931IsIEPresent(pMes->DateTime)) {
|
|
if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_DATETIME](pTrunk, Q931GetIEPtr(pMes->DateTime,pMes->buf), OBuf, &Octet))!=0)
|
|
return rc;
|
|
}
|
|
|
|
/* Keypad Facility */
|
|
if (Q931IsIEPresent(pMes->KeypadFac)) {
|
|
if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_KEYPAD_FACILITY](pTrunk, Q931GetIEPtr(pMes->KeypadFac,pMes->buf), OBuf, &Octet))!=0)
|
|
return rc;
|
|
}
|
|
|
|
/* Signal */
|
|
if (Q931IsIEPresent(pMes->Signal)) {
|
|
if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_SIGNAL](pTrunk, Q931GetIEPtr(pMes->Signal,pMes->buf), OBuf, &Octet))!=0)
|
|
return rc;
|
|
}
|
|
|
|
/* Calling Party Number */
|
|
if (Q931IsIEPresent(pMes->CallingNum)) {
|
|
if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CALLING_PARTY_NUMBER](pTrunk, Q931GetIEPtr(pMes->CallingNum,pMes->buf), OBuf, &Octet))!=0)
|
|
return rc;
|
|
}
|
|
|
|
/* Calling Party Subaddress */
|
|
if (Q931IsIEPresent(pMes->CallingSub)) {
|
|
if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CALLING_PARTY_SUBADDRESS](pTrunk, Q931GetIEPtr(pMes->CallingSub,pMes->buf), OBuf, &Octet))!=0)
|
|
return rc;
|
|
}
|
|
|
|
/* Called Party number */
|
|
if (Q931IsIEPresent(pMes->CalledNum)) {
|
|
if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CALLED_PARTY_NUMBER](pTrunk, Q931GetIEPtr(pMes->CalledNum,pMes->buf), OBuf, &Octet))!=0)
|
|
return rc;
|
|
}
|
|
|
|
/* Called party subaddress */
|
|
if (Q931IsIEPresent(pMes->CalledSub)) {
|
|
if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_CALLED_PARTY_SUBADDRESS](pTrunk, Q931GetIEPtr(pMes->CalledSub,pMes->buf), OBuf, &Octet))!=0)
|
|
return rc;
|
|
}
|
|
|
|
/* Transit network selection */
|
|
if (Q931IsIEPresent(pMes->TransNetSel)) {
|
|
if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_TRANSIT_NETWORK_SELECTION](pTrunk, Q931GetIEPtr(pMes->TransNetSel,pMes->buf), OBuf, &Octet))!=0)
|
|
return rc;
|
|
}
|
|
|
|
/* Repeat Indicator */
|
|
if (Q931IsIEPresent(pMes->LLRepeatInd)) {
|
|
rc = Q931E_UNKNOWN_IE;/* TODO */
|
|
}
|
|
|
|
/* Low Layer Compatibility */
|
|
if (Q931IsIEPresent(pMes->LLComp)) {
|
|
if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_LOW_LAYER_COMPATIBILITY](pTrunk, Q931GetIEPtr(pMes->LLComp,pMes->buf), OBuf, &Octet))!=0)
|
|
return rc;
|
|
}
|
|
|
|
/* High Layer Compatibility */
|
|
if (Q931IsIEPresent(pMes->HLComp)) {
|
|
if ((rc = Q931Pie[pTrunk->Dialect][Q931ie_HIGH_LAYER_COMPATIBILITY](pTrunk, Q931GetIEPtr(pMes->HLComp,pMes->buf), OBuf, &Octet))!=0)
|
|
return rc;
|
|
}
|
|
|
|
*OSize = Octet;
|
|
return rc;
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
Function: ATT5ESSUmes_0x0f
|
|
|
|
*****************************************************************************/
|
|
L3INT ATT5ESSUmes_0x0f(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size)
|
|
{
|
|
if (mes->ProtDisc == 8) {
|
|
return Q931Umes_ConnectAck(pTrunk, IBuf, mes, IOff, Size);
|
|
}
|
|
|
|
if (mes->ProtDisc == 3) {
|
|
return Q931Umes_Service(pTrunk, IBuf, mes, IOff, Size);
|
|
}
|
|
|
|
return Q931E_UNKNOWN_MESSAGE;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
|
|
Function: ATT5ESSPmes_0x0f
|
|
|
|
*****************************************************************************/
|
|
L3INT ATT5ESSPmes_0x0f(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize)
|
|
{
|
|
Q931mes_Generic *mes = (Q931mes_Generic *)IBuf;
|
|
|
|
if (mes->ProtDisc == 8) {
|
|
return Q931Pmes_ConnectAck(pTrunk, IBuf, ISize, OBuf, OSize);
|
|
}
|
|
|
|
if (mes->ProtDisc == 3) {
|
|
return Q931Pmes_Service(pTrunk, IBuf, ISize, OBuf, OSize);
|
|
}
|
|
|
|
return Q931E_UNKNOWN_MESSAGE;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
|
|
Function: ATT5ESSUmes_0x07
|
|
|
|
*****************************************************************************/
|
|
L3INT ATT5ESSUmes_0x07(Q931_TrunkInfo_t *pTrunk, L3UCHAR *IBuf, Q931mes_Generic *mes, L3INT IOff, L3INT Size)
|
|
{
|
|
if (mes->ProtDisc == 8) {
|
|
return Q931Umes_Connect(pTrunk, IBuf, mes, IOff, Size);
|
|
}
|
|
|
|
if (mes->ProtDisc == 3) {
|
|
return Q931Umes_ServiceAck(pTrunk, IBuf, mes, IOff, Size);
|
|
}
|
|
|
|
return Q931E_UNKNOWN_MESSAGE;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
|
|
Function: ATT5ESSPmes_0x07
|
|
|
|
*****************************************************************************/
|
|
L3INT ATT5ESSPmes_0x07(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize)
|
|
{
|
|
Q931mes_Generic *mes = (Q931mes_Generic *)IBuf;
|
|
|
|
if (mes->ProtDisc == 8) {
|
|
return Q931Pmes_Connect(pTrunk, IBuf, ISize, OBuf, OSize);
|
|
}
|
|
|
|
if (mes->ProtDisc == 3) {
|
|
return Q931Pmes_ServiceAck(pTrunk, IBuf, ISize, OBuf, OSize);
|
|
}
|
|
|
|
return Q931E_UNKNOWN_MESSAGE;
|
|
}
|