mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-24 22:58:21 +00:00
........ r369001 | kpfleming | 2012-06-15 10:56:08 -0500 (Fri, 15 Jun 2012) | 11 lines Add support-level indications to many more source files. Since we now have tools that scan through the source tree looking for files with specific support levels, we need to ensure that every file that is a component of a 'core' or 'extended' module (or the main Asterisk binary) is explicitly marked with its support level. This patch adds support-level indications to many more source files in tree, but avoids adding them to third-party libraries that are included in the tree and to source files that don't end up involved in Asterisk itself. ........ r369002 | kpfleming | 2012-06-15 10:57:14 -0500 (Fri, 15 Jun 2012) | 3 lines Add a script to enable finding source files without support-levels defined. ........ Merged revisions 369001-369002 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ Merged revisions 369005 from http://svn.asterisk.org/svn/asterisk/branches/10 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@369013 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1768 lines
51 KiB
C
1768 lines
51 KiB
C
/*
|
|
* Chan_Misdn -- Channel Driver for Asterisk
|
|
*
|
|
* Interface to mISDN
|
|
*
|
|
* Copyright (C) 2004, Christian Richter
|
|
*
|
|
* Christian Richter <crich@beronet.com>
|
|
*
|
|
* This program is free software, distributed under the terms of
|
|
* the GNU General Public License
|
|
*/
|
|
|
|
/*! \file
|
|
* \brief Interface to mISDN - message parser
|
|
* \author Christian Richter <crich@beronet.com>
|
|
*/
|
|
|
|
/*** MODULEINFO
|
|
<support_level>extended</support_level>
|
|
***/
|
|
|
|
#include "isdn_lib_intern.h"
|
|
|
|
|
|
#include "isdn_lib.h"
|
|
|
|
#include "ie.c"
|
|
|
|
/*!
|
|
* \internal
|
|
* \brief Build the name, number, name/number display message string
|
|
*
|
|
* \param display Display buffer to fill in
|
|
* \param display_length Length of the display buffer to fill in
|
|
* \param display_format Display format enumeration
|
|
* \param name Name string to use
|
|
* \param number Number string to use
|
|
*
|
|
* \return Nothing
|
|
*/
|
|
static void build_display_str(char *display, size_t display_length, int display_format, const char *name, const char *number)
|
|
{
|
|
display[0] = 0;
|
|
switch (display_format) {
|
|
default:
|
|
case 0: /* none */
|
|
break;
|
|
|
|
case 1: /* name */
|
|
snprintf(display, display_length, "%s", name);
|
|
break;
|
|
|
|
case 2: /* number */
|
|
snprintf(display, display_length, "%s", number);
|
|
break;
|
|
|
|
case 3: /* both */
|
|
if (name[0] || number[0]) {
|
|
snprintf(display, display_length, "\"%s\" <%s>", name, number);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*!
|
|
* \internal
|
|
* \brief Encode the Facility IE and put it into the message structure.
|
|
*
|
|
* \param ntmode Where the encoded facility was put when in NT mode.
|
|
* \param msg General message structure
|
|
* \param fac Data to encode into the facility ie.
|
|
* \param nt TRUE if in NT mode.
|
|
*
|
|
* \return Nothing
|
|
*/
|
|
static void enc_ie_facility(unsigned char **ntmode, msg_t *msg, struct FacParm *fac, int nt)
|
|
{
|
|
int len;
|
|
Q931_info_t *qi;
|
|
unsigned char *p;
|
|
unsigned char buf[256];
|
|
|
|
len = encodeFac(buf, fac);
|
|
if (len <= 0) {
|
|
/*
|
|
* mISDN does not know how to build the requested facility structure
|
|
* Clear facility information
|
|
*/
|
|
fac->Function = Fac_None;
|
|
return;
|
|
}
|
|
|
|
p = msg_put(msg, len);
|
|
if (nt) {
|
|
*ntmode = p + 1;
|
|
} else {
|
|
qi = (Q931_info_t *) (msg->data + mISDN_HEADER_LEN);
|
|
qi->QI_ELEMENT(facility) = p - (unsigned char *) qi - sizeof(Q931_info_t);
|
|
}
|
|
|
|
memcpy(p, buf, len);
|
|
|
|
/* Clear facility information */
|
|
fac->Function = Fac_None;
|
|
}
|
|
|
|
/*!
|
|
* \internal
|
|
* \brief Decode the Facility IE.
|
|
*
|
|
* \param p Encoded facility ie data to decode. (NT mode)
|
|
* \param qi Encoded facility ie data to decode. (TE mode)
|
|
* \param fac Where to put the decoded facility ie data if it is available.
|
|
* \param nt TRUE if in NT mode.
|
|
* \param bc Associated B channel
|
|
*
|
|
* \return Nothing
|
|
*/
|
|
static void dec_ie_facility(unsigned char *p, Q931_info_t *qi, struct FacParm *fac, int nt, struct misdn_bchannel *bc)
|
|
{
|
|
fac->Function = Fac_None;
|
|
|
|
if (!nt) {
|
|
p = NULL;
|
|
if (qi->QI_ELEMENT(facility)) {
|
|
p = (unsigned char *) qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(facility) + 1;
|
|
}
|
|
}
|
|
if (!p) {
|
|
return;
|
|
}
|
|
|
|
if (decodeFac(p, fac)) {
|
|
cb_log(3, bc->port, "Decoding facility ie failed! Unrecognized facility message?\n");
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static void set_channel(struct misdn_bchannel *bc, int channel)
|
|
{
|
|
|
|
cb_log(3,bc->port,"set_channel: bc->channel:%d channel:%d\n", bc->channel, channel);
|
|
|
|
|
|
if (channel==0xff) {
|
|
/* any channel */
|
|
channel=-1;
|
|
}
|
|
|
|
/* ALERT: is that everytime true ? */
|
|
if (channel > 0 && bc->nt ) {
|
|
|
|
if (bc->channel && ( bc->channel != 0xff) ) {
|
|
cb_log(0,bc->port,"We already have a channel (%d)\n", bc->channel);
|
|
} else {
|
|
bc->channel = channel;
|
|
cb_event(EVENT_NEW_CHANNEL,bc,NULL);
|
|
}
|
|
}
|
|
|
|
if (channel > 0 && !bc->nt ) {
|
|
bc->channel = channel;
|
|
cb_event(EVENT_NEW_CHANNEL,bc,NULL);
|
|
}
|
|
}
|
|
|
|
static void parse_proceeding (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
|
|
{
|
|
int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
|
|
CALL_PROCEEDING_t *proceeding = (CALL_PROCEEDING_t *) (msg->data + HEADER_LEN);
|
|
//struct misdn_stack *stack=get_stack_by_bc(bc);
|
|
|
|
{
|
|
int exclusive, channel;
|
|
dec_ie_channel_id(proceeding->CHANNEL_ID, (Q931_info_t *)proceeding, &exclusive, &channel, nt,bc);
|
|
|
|
set_channel(bc,channel);
|
|
|
|
}
|
|
|
|
dec_ie_progress(proceeding->PROGRESS, (Q931_info_t *)proceeding, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc);
|
|
|
|
dec_ie_facility(proceeding->FACILITY, (Q931_info_t *) proceeding, &bc->fac_in, nt, bc);
|
|
|
|
/* dec_ie_redir_dn */
|
|
|
|
#ifdef DEBUG
|
|
printf("Parsing PROCEEDING Msg\n");
|
|
#endif
|
|
}
|
|
static msg_t *build_proceeding (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
|
|
{
|
|
int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
|
|
CALL_PROCEEDING_t *proceeding;
|
|
msg_t *msg =(msg_t*)create_l3msg(CC_PROCEEDING | REQUEST, MT_CALL_PROCEEDING, bc?bc->l3_id:-1, sizeof(CALL_PROCEEDING_t) ,nt);
|
|
|
|
proceeding=(CALL_PROCEEDING_t*)((msg->data+HEADER_LEN));
|
|
|
|
enc_ie_channel_id(&proceeding->CHANNEL_ID, msg, 1,bc->channel, nt,bc);
|
|
|
|
if (nt)
|
|
enc_ie_progress(&proceeding->PROGRESS, msg, 0, nt?1:5, 8, nt,bc);
|
|
|
|
if (bc->fac_out.Function != Fac_None) {
|
|
enc_ie_facility(&proceeding->FACILITY, msg, &bc->fac_out, nt);
|
|
}
|
|
|
|
/* enc_ie_redir_dn */
|
|
|
|
#ifdef DEBUG
|
|
printf("Building PROCEEDING Msg\n");
|
|
#endif
|
|
return msg;
|
|
}
|
|
|
|
static void parse_alerting (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
|
|
{
|
|
int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
|
|
ALERTING_t *alerting = (ALERTING_t *) (msg->data + HEADER_LEN);
|
|
//Q931_info_t *qi=(Q931_info_t*)(msg->data+HEADER_LEN);
|
|
|
|
dec_ie_facility(alerting->FACILITY, (Q931_info_t *) alerting, &bc->fac_in, nt, bc);
|
|
|
|
/* dec_ie_redir_dn */
|
|
|
|
dec_ie_progress(alerting->PROGRESS, (Q931_info_t *)alerting, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc);
|
|
|
|
#ifdef DEBUG
|
|
printf("Parsing ALERTING Msg\n");
|
|
#endif
|
|
|
|
|
|
}
|
|
|
|
static msg_t *build_alerting (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
|
|
{
|
|
int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
|
|
ALERTING_t *alerting;
|
|
msg_t *msg =(msg_t*)create_l3msg(CC_ALERTING | REQUEST, MT_ALERTING, bc?bc->l3_id:-1, sizeof(ALERTING_t) ,nt);
|
|
|
|
alerting=(ALERTING_t*)((msg->data+HEADER_LEN));
|
|
|
|
enc_ie_channel_id(&alerting->CHANNEL_ID, msg, 1,bc->channel, nt,bc);
|
|
|
|
if (nt)
|
|
enc_ie_progress(&alerting->PROGRESS, msg, 0, nt?1:5, 8, nt,bc);
|
|
|
|
if (bc->fac_out.Function != Fac_None) {
|
|
enc_ie_facility(&alerting->FACILITY, msg, &bc->fac_out, nt);
|
|
}
|
|
|
|
/* enc_ie_redir_dn */
|
|
|
|
#ifdef DEBUG
|
|
printf("Building ALERTING Msg\n");
|
|
#endif
|
|
return msg;
|
|
}
|
|
|
|
|
|
static void parse_progress (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
|
|
{
|
|
int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
|
|
PROGRESS_t *progress = (PROGRESS_t *) (msg->data + HEADER_LEN);
|
|
//Q931_info_t *qi=(Q931_info_t*)(msg->data+HEADER_LEN);
|
|
|
|
dec_ie_progress(progress->PROGRESS, (Q931_info_t *)progress, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc);
|
|
|
|
dec_ie_facility(progress->FACILITY, (Q931_info_t *) progress, &bc->fac_in, nt, bc);
|
|
|
|
#ifdef DEBUG
|
|
printf("Parsing PROGRESS Msg\n");
|
|
#endif
|
|
}
|
|
|
|
static msg_t *build_progress (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
|
|
{
|
|
int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
|
|
PROGRESS_t *progress;
|
|
msg_t *msg =(msg_t*)create_l3msg(CC_PROGRESS | REQUEST, MT_PROGRESS, bc?bc->l3_id:-1, sizeof(PROGRESS_t) ,nt);
|
|
|
|
progress=(PROGRESS_t*)((msg->data+HEADER_LEN));
|
|
|
|
if (bc->fac_out.Function != Fac_None) {
|
|
enc_ie_facility(&progress->FACILITY, msg, &bc->fac_out, nt);
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
printf("Building PROGRESS Msg\n");
|
|
#endif
|
|
return msg;
|
|
}
|
|
|
|
#if defined(AST_MISDN_ENHANCEMENTS)
|
|
/*!
|
|
* \internal
|
|
* \brief Extract the SETUP message's BC, HLC, and LLC encoded ie contents.
|
|
*
|
|
* \param setup Indexed setup message contents
|
|
* \param nt TRUE if in NT mode.
|
|
* \param bc Associated B channel
|
|
*
|
|
* \return Nothing
|
|
*/
|
|
static void extract_setup_Bc_Hlc_Llc(SETUP_t *setup, int nt, struct misdn_bchannel *bc)
|
|
{
|
|
__u8 *p;
|
|
Q931_info_t *qi;
|
|
|
|
qi = (Q931_info_t *) setup;
|
|
|
|
/* Extract Bearer Capability */
|
|
if (nt) {
|
|
p = (__u8 *) setup->BEARER;
|
|
} else {
|
|
if (qi->QI_ELEMENT(bearer_capability)) {
|
|
p = (__u8 *) qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(bearer_capability) + 1;
|
|
} else {
|
|
p = NULL;
|
|
}
|
|
}
|
|
if (!p || *p == 0 || sizeof(bc->setup_bc_hlc_llc.Bc.Contents) < *p) {
|
|
bc->setup_bc_hlc_llc.Bc.Length = 0;
|
|
} else {
|
|
bc->setup_bc_hlc_llc.Bc.Length = *p;
|
|
memcpy(bc->setup_bc_hlc_llc.Bc.Contents, p + 1, *p);
|
|
}
|
|
|
|
/* Extract Low Layer Compatibility */
|
|
if (nt) {
|
|
p = (__u8 *) setup->LLC;
|
|
} else {
|
|
if (qi->QI_ELEMENT(llc)) {
|
|
p = (__u8 *) qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(llc) + 1;
|
|
} else {
|
|
p = NULL;
|
|
}
|
|
}
|
|
if (!p || *p == 0 || sizeof(bc->setup_bc_hlc_llc.Llc.Contents) < *p) {
|
|
bc->setup_bc_hlc_llc.Llc.Length = 0;
|
|
} else {
|
|
bc->setup_bc_hlc_llc.Llc.Length = *p;
|
|
memcpy(bc->setup_bc_hlc_llc.Llc.Contents, p + 1, *p);
|
|
}
|
|
|
|
/* Extract High Layer Compatibility */
|
|
if (nt) {
|
|
p = (__u8 *) setup->HLC;
|
|
} else {
|
|
if (qi->QI_ELEMENT(hlc)) {
|
|
p = (__u8 *) qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(hlc) + 1;
|
|
} else {
|
|
p = NULL;
|
|
}
|
|
}
|
|
if (!p || *p == 0 || sizeof(bc->setup_bc_hlc_llc.Hlc.Contents) < *p) {
|
|
bc->setup_bc_hlc_llc.Hlc.Length = 0;
|
|
} else {
|
|
bc->setup_bc_hlc_llc.Hlc.Length = *p;
|
|
memcpy(bc->setup_bc_hlc_llc.Hlc.Contents, p + 1, *p);
|
|
}
|
|
}
|
|
#endif /* defined(AST_MISDN_ENHANCEMENTS) */
|
|
|
|
static void parse_setup (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
|
|
{
|
|
int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
|
|
SETUP_t *setup = (SETUP_t *) (msg->data + HEADER_LEN);
|
|
Q931_info_t *qi = (Q931_info_t *) (msg->data + HEADER_LEN);
|
|
int type;
|
|
int plan;
|
|
int present;
|
|
int screen;
|
|
int reason;
|
|
|
|
#ifdef DEBUG
|
|
printf("Parsing SETUP Msg\n");
|
|
#endif
|
|
|
|
dec_ie_calling_pn(setup->CALLING_PN, qi, &type, &plan, &present, &screen, bc->caller.number, sizeof(bc->caller.number), nt, bc);
|
|
bc->caller.number_type = type;
|
|
bc->caller.number_plan = plan;
|
|
switch (present) {
|
|
default:
|
|
case 0:
|
|
bc->caller.presentation = 0; /* presentation allowed */
|
|
break;
|
|
case 1:
|
|
bc->caller.presentation = 1; /* presentation restricted */
|
|
break;
|
|
case 2:
|
|
bc->caller.presentation = 2; /* Number not available */
|
|
break;
|
|
}
|
|
if (0 <= screen) {
|
|
bc->caller.screening = screen;
|
|
} else {
|
|
bc->caller.screening = 0; /* Unscreened */
|
|
}
|
|
|
|
dec_ie_facility(setup->FACILITY, (Q931_info_t *) setup, &bc->fac_in, nt, bc);
|
|
|
|
dec_ie_called_pn(setup->CALLED_PN, (Q931_info_t *) setup, &type, &plan, bc->dialed.number, sizeof(bc->dialed.number), nt, bc);
|
|
bc->dialed.number_type = type;
|
|
bc->dialed.number_plan = plan;
|
|
|
|
dec_ie_keypad(setup->KEYPAD, (Q931_info_t *) setup, bc->keypad, sizeof(bc->keypad), nt, bc);
|
|
|
|
dec_ie_complete(setup->COMPLETE, (Q931_info_t *) setup, &bc->sending_complete, nt, bc);
|
|
|
|
dec_ie_redir_nr(setup->REDIR_NR, (Q931_info_t *) setup, &type, &plan, &present, &screen, &reason, bc->redirecting.from.number, sizeof(bc->redirecting.from.number), nt, bc);
|
|
bc->redirecting.from.number_type = type;
|
|
bc->redirecting.from.number_plan = plan;
|
|
switch (present) {
|
|
default:
|
|
case 0:
|
|
bc->redirecting.from.presentation = 0; /* presentation allowed */
|
|
break;
|
|
case 1:
|
|
bc->redirecting.from.presentation = 1; /* presentation restricted */
|
|
break;
|
|
case 2:
|
|
bc->redirecting.from.presentation = 2; /* Number not available */
|
|
break;
|
|
}
|
|
if (0 <= screen) {
|
|
bc->redirecting.from.screening = screen;
|
|
} else {
|
|
bc->redirecting.from.screening = 0; /* Unscreened */
|
|
}
|
|
if (0 <= reason) {
|
|
bc->redirecting.reason = reason;
|
|
} else {
|
|
bc->redirecting.reason = mISDN_REDIRECTING_REASON_UNKNOWN;
|
|
}
|
|
|
|
{
|
|
int coding, capability, mode, rate, multi, user, async, urate, stopbits, dbits, parity;
|
|
|
|
dec_ie_bearer(setup->BEARER, (Q931_info_t *)setup, &coding, &capability, &mode, &rate, &multi, &user, &async, &urate, &stopbits, &dbits, &parity, nt,bc);
|
|
switch (capability) {
|
|
case -1: bc->capability=INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
|
|
break;
|
|
case 0: bc->capability=INFO_CAPABILITY_SPEECH;
|
|
break;
|
|
case 18: bc->capability=INFO_CAPABILITY_VIDEO;
|
|
break;
|
|
case 8: bc->capability=INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
|
|
bc->user1 = user;
|
|
bc->urate = urate;
|
|
|
|
bc->rate = rate;
|
|
bc->mode = mode;
|
|
break;
|
|
case 9: bc->capability=INFO_CAPABILITY_DIGITAL_RESTRICTED;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
switch(user) {
|
|
case 2:
|
|
bc->law=INFO_CODEC_ULAW;
|
|
break;
|
|
case 3:
|
|
bc->law=INFO_CODEC_ALAW;
|
|
break;
|
|
default:
|
|
bc->law=INFO_CODEC_ALAW;
|
|
|
|
}
|
|
|
|
bc->capability=capability;
|
|
}
|
|
{
|
|
int exclusive, channel;
|
|
dec_ie_channel_id(setup->CHANNEL_ID, (Q931_info_t *)setup, &exclusive, &channel, nt,bc);
|
|
|
|
set_channel(bc,channel);
|
|
}
|
|
|
|
{
|
|
int protocol ;
|
|
dec_ie_useruser(setup->USER_USER, (Q931_info_t *)setup, &protocol, bc->uu, &bc->uulen, nt,bc);
|
|
if (bc->uulen) cb_log(1,bc->port,"USERUESRINFO:%s\n",bc->uu);
|
|
else
|
|
cb_log(1,bc->port,"NO USERUESRINFO\n");
|
|
}
|
|
|
|
dec_ie_progress(setup->PROGRESS, (Q931_info_t *)setup, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc);
|
|
|
|
#if defined(AST_MISDN_ENHANCEMENTS)
|
|
extract_setup_Bc_Hlc_Llc(setup, nt, bc);
|
|
#endif /* defined(AST_MISDN_ENHANCEMENTS) */
|
|
}
|
|
|
|
#define ANY_CHANNEL 0xff /* IE attribute for 'any channel' */
|
|
static msg_t *build_setup (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
|
|
{
|
|
int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
|
|
SETUP_t *setup;
|
|
msg_t *msg =(msg_t*)create_l3msg(CC_SETUP | REQUEST, MT_SETUP, bc?bc->l3_id:-1, sizeof(SETUP_t) ,nt);
|
|
int is_ptp;
|
|
enum FacFunction fac_type;
|
|
|
|
setup=(SETUP_t*)((msg->data+HEADER_LEN));
|
|
|
|
if (bc->channel == 0 || bc->channel == ANY_CHANNEL || bc->channel==-1)
|
|
enc_ie_channel_id(&setup->CHANNEL_ID, msg, 0, bc->channel, nt,bc);
|
|
else
|
|
enc_ie_channel_id(&setup->CHANNEL_ID, msg, 1, bc->channel, nt,bc);
|
|
|
|
fac_type = bc->fac_out.Function;
|
|
if (fac_type != Fac_None) {
|
|
enc_ie_facility(&setup->FACILITY, msg, &bc->fac_out, nt);
|
|
}
|
|
|
|
enc_ie_calling_pn(&setup->CALLING_PN, msg, bc->caller.number_type, bc->caller.number_plan,
|
|
bc->caller.presentation, bc->caller.screening, bc->caller.number, nt, bc);
|
|
|
|
if (bc->dialed.number[0]) {
|
|
enc_ie_called_pn(&setup->CALLED_PN, msg, bc->dialed.number_type, bc->dialed.number_plan, bc->dialed.number, nt, bc);
|
|
}
|
|
|
|
switch (bc->outgoing_colp) {
|
|
case 0:/* pass */
|
|
case 1:/* restricted */
|
|
is_ptp = misdn_lib_is_ptp(bc->port);
|
|
if (bc->redirecting.from.number[0]
|
|
&& ((!is_ptp && nt)
|
|
|| (is_ptp
|
|
#if defined(AST_MISDN_ENHANCEMENTS)
|
|
/*
|
|
* There is no need to send out this ie when we are also sending
|
|
* a Fac_DivertingLegInformation2 as well. The
|
|
* Fac_DivertingLegInformation2 supercedes the information in
|
|
* this ie.
|
|
*/
|
|
&& fac_type != Fac_DivertingLegInformation2
|
|
#endif /* defined(AST_MISDN_ENHANCEMENTS) */
|
|
))) {
|
|
#if 1
|
|
/* ETSI and Q.952 do not define the screening field */
|
|
enc_ie_redir_nr(&setup->REDIR_NR, msg, bc->redirecting.from.number_type,
|
|
bc->redirecting.from.number_plan, bc->redirecting.from.presentation, 0,
|
|
bc->redirecting.reason, bc->redirecting.from.number, nt, bc);
|
|
#else
|
|
/* Q.931 defines the screening field */
|
|
enc_ie_redir_nr(&setup->REDIR_NR, msg, bc->redirecting.from.number_type,
|
|
bc->redirecting.from.number_plan, bc->redirecting.from.presentation,
|
|
bc->redirecting.from.screening, bc->redirecting.reason,
|
|
bc->redirecting.from.number, nt, bc);
|
|
#endif
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (bc->keypad[0]) {
|
|
enc_ie_keypad(&setup->KEYPAD, msg, bc->keypad, nt,bc);
|
|
}
|
|
|
|
|
|
|
|
if (*bc->display) {
|
|
enc_ie_display(&setup->DISPLAY, msg, bc->display, nt, bc);
|
|
} else if (nt && bc->caller.presentation == 0) {
|
|
char display[sizeof(bc->display)];
|
|
|
|
/* Presentation is allowed */
|
|
build_display_str(display, sizeof(display), bc->display_setup, bc->caller.name, bc->caller.number);
|
|
if (display[0]) {
|
|
enc_ie_display(&setup->DISPLAY, msg, display, nt, bc);
|
|
}
|
|
}
|
|
|
|
{
|
|
int coding = 0;
|
|
int capability;
|
|
int mode = 0; /* 2 for packet! */
|
|
int user;
|
|
int rate = 0x10;
|
|
|
|
switch (bc->law) {
|
|
case INFO_CODEC_ULAW: user=2;
|
|
break;
|
|
case INFO_CODEC_ALAW: user=3;
|
|
break;
|
|
default:
|
|
user=3;
|
|
}
|
|
|
|
switch (bc->capability) {
|
|
case INFO_CAPABILITY_SPEECH: capability = 0;
|
|
break;
|
|
case INFO_CAPABILITY_DIGITAL_UNRESTRICTED: capability = 8;
|
|
user=-1;
|
|
mode=bc->mode;
|
|
rate=bc->rate;
|
|
break;
|
|
case INFO_CAPABILITY_DIGITAL_RESTRICTED: capability = 9;
|
|
user=-1;
|
|
break;
|
|
default:
|
|
capability=bc->capability;
|
|
}
|
|
|
|
enc_ie_bearer(&setup->BEARER, msg, coding, capability, mode, rate, -1, user, nt,bc);
|
|
}
|
|
|
|
if (bc->sending_complete) {
|
|
enc_ie_complete(&setup->COMPLETE,msg, bc->sending_complete, nt, bc);
|
|
}
|
|
|
|
if (bc->uulen) {
|
|
int protocol=4;
|
|
enc_ie_useruser(&setup->USER_USER, msg, protocol, bc->uu, bc->uulen, nt,bc);
|
|
cb_log(1,bc->port,"ENCODING USERUESRINFO:%s\n",bc->uu);
|
|
}
|
|
|
|
#if defined(AST_MISDN_ENHANCEMENTS)
|
|
extract_setup_Bc_Hlc_Llc(setup, nt, bc);
|
|
#endif /* defined(AST_MISDN_ENHANCEMENTS) */
|
|
|
|
#ifdef DEBUG
|
|
printf("Building SETUP Msg\n");
|
|
#endif
|
|
return msg;
|
|
}
|
|
|
|
static void parse_connect (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
|
|
{
|
|
int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
|
|
CONNECT_t *connect = (CONNECT_t *) (msg->data + HEADER_LEN);
|
|
int type;
|
|
int plan;
|
|
int pres;
|
|
int screen;
|
|
|
|
bc->ces = connect->ces;
|
|
|
|
dec_ie_progress(connect->PROGRESS, (Q931_info_t *)connect, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc);
|
|
|
|
dec_ie_connected_pn(connect->CONNECT_PN, (Q931_info_t *) connect, &type, &plan,
|
|
&pres, &screen, bc->connected.number, sizeof(bc->connected.number), nt, bc);
|
|
bc->connected.number_type = type;
|
|
bc->connected.number_plan = plan;
|
|
switch (pres) {
|
|
default:
|
|
case 0:
|
|
bc->connected.presentation = 0; /* presentation allowed */
|
|
break;
|
|
case 1:
|
|
bc->connected.presentation = 1; /* presentation restricted */
|
|
break;
|
|
case 2:
|
|
bc->connected.presentation = 2; /* Number not available */
|
|
break;
|
|
}
|
|
if (0 <= screen) {
|
|
bc->connected.screening = screen;
|
|
} else {
|
|
bc->connected.screening = 0; /* Unscreened */
|
|
}
|
|
|
|
dec_ie_facility(connect->FACILITY, (Q931_info_t *) connect, &bc->fac_in, nt, bc);
|
|
|
|
/*
|
|
cb_log(1,bc->port,"CONNETED PN: %s cpn_dialplan:%d\n", connected_pn, type);
|
|
*/
|
|
|
|
#ifdef DEBUG
|
|
printf("Parsing CONNECT Msg\n");
|
|
#endif
|
|
}
|
|
|
|
static msg_t *build_connect (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
|
|
{
|
|
int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
|
|
CONNECT_t *connect;
|
|
msg_t *msg =(msg_t*)create_l3msg(CC_CONNECT | REQUEST, MT_CONNECT, bc?bc->l3_id:-1, sizeof(CONNECT_t) ,nt);
|
|
|
|
cb_log(6,bc->port,"BUILD_CONNECT: bc:%p bc->l3id:%d, nt:%d\n",bc,bc->l3_id,nt);
|
|
|
|
connect=(CONNECT_t*)((msg->data+HEADER_LEN));
|
|
|
|
if (nt) {
|
|
time_t now;
|
|
time(&now);
|
|
enc_ie_date(&connect->DATE, msg, now, nt,bc);
|
|
}
|
|
|
|
switch (bc->outgoing_colp) {
|
|
case 0:/* pass */
|
|
case 1:/* restricted */
|
|
enc_ie_connected_pn(&connect->CONNECT_PN, msg, bc->connected.number_type,
|
|
bc->connected.number_plan, bc->connected.presentation,
|
|
bc->connected.screening, bc->connected.number, nt, bc);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (nt && bc->connected.presentation == 0) {
|
|
char display[sizeof(bc->display)];
|
|
|
|
/* Presentation is allowed */
|
|
build_display_str(display, sizeof(display), bc->display_connected, bc->connected.name, bc->connected.number);
|
|
if (display[0]) {
|
|
enc_ie_display(&connect->DISPLAY, msg, display, nt, bc);
|
|
}
|
|
}
|
|
|
|
if (bc->fac_out.Function != Fac_None) {
|
|
enc_ie_facility(&connect->FACILITY, msg, &bc->fac_out, nt);
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
printf("Building CONNECT Msg\n");
|
|
#endif
|
|
return msg;
|
|
}
|
|
|
|
static void parse_setup_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
|
|
{
|
|
int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
|
|
SETUP_ACKNOWLEDGE_t *setup_acknowledge = (SETUP_ACKNOWLEDGE_t *) (msg->data + HEADER_LEN);
|
|
|
|
{
|
|
int exclusive, channel;
|
|
dec_ie_channel_id(setup_acknowledge->CHANNEL_ID, (Q931_info_t *)setup_acknowledge, &exclusive, &channel, nt,bc);
|
|
|
|
|
|
set_channel(bc, channel);
|
|
}
|
|
|
|
dec_ie_progress(setup_acknowledge->PROGRESS, (Q931_info_t *)setup_acknowledge, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc);
|
|
|
|
dec_ie_facility(setup_acknowledge->FACILITY, (Q931_info_t *) setup_acknowledge, &bc->fac_in, nt, bc);
|
|
|
|
#ifdef DEBUG
|
|
printf("Parsing SETUP_ACKNOWLEDGE Msg\n");
|
|
#endif
|
|
|
|
|
|
}
|
|
|
|
static msg_t *build_setup_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
|
|
{
|
|
int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
|
|
SETUP_ACKNOWLEDGE_t *setup_acknowledge;
|
|
msg_t *msg =(msg_t*)create_l3msg(CC_SETUP_ACKNOWLEDGE | REQUEST, MT_SETUP_ACKNOWLEDGE, bc?bc->l3_id:-1, sizeof(SETUP_ACKNOWLEDGE_t) ,nt);
|
|
|
|
setup_acknowledge=(SETUP_ACKNOWLEDGE_t*)((msg->data+HEADER_LEN));
|
|
|
|
enc_ie_channel_id(&setup_acknowledge->CHANNEL_ID, msg, 1,bc->channel, nt,bc);
|
|
|
|
if (nt)
|
|
enc_ie_progress(&setup_acknowledge->PROGRESS, msg, 0, nt?1:5, 8, nt,bc);
|
|
|
|
if (bc->fac_out.Function != Fac_None) {
|
|
enc_ie_facility(&setup_acknowledge->FACILITY, msg, &bc->fac_out, nt);
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
printf("Building SETUP_ACKNOWLEDGE Msg\n");
|
|
#endif
|
|
return msg;
|
|
}
|
|
|
|
static void parse_connect_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("Parsing CONNECT_ACKNOWLEDGE Msg\n");
|
|
#endif
|
|
|
|
|
|
}
|
|
|
|
static msg_t *build_connect_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
|
|
{
|
|
int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
|
|
CONNECT_ACKNOWLEDGE_t *connect_acknowledge;
|
|
msg_t *msg =(msg_t*)create_l3msg(CC_CONNECT | RESPONSE, MT_CONNECT, bc?bc->l3_id:-1, sizeof(CONNECT_ACKNOWLEDGE_t) ,nt);
|
|
|
|
connect_acknowledge=(CONNECT_ACKNOWLEDGE_t*)((msg->data+HEADER_LEN));
|
|
|
|
enc_ie_channel_id(&connect_acknowledge->CHANNEL_ID, msg, 1, bc->channel, nt,bc);
|
|
|
|
#ifdef DEBUG
|
|
printf("Building CONNECT_ACKNOWLEDGE Msg\n");
|
|
#endif
|
|
return msg;
|
|
}
|
|
|
|
static void parse_user_information (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("Parsing USER_INFORMATION Msg\n");
|
|
#endif
|
|
|
|
|
|
}
|
|
|
|
static msg_t *build_user_information (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
|
|
{
|
|
msg_t *msg =(msg_t*)create_l3msg(CC_USER_INFORMATION | REQUEST, MT_USER_INFORMATION, bc?bc->l3_id:-1, sizeof(USER_INFORMATION_t) ,nt);
|
|
|
|
#ifdef DEBUG
|
|
printf("Building USER_INFORMATION Msg\n");
|
|
#endif
|
|
return msg;
|
|
}
|
|
|
|
static void parse_suspend_reject (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("Parsing SUSPEND_REJECT Msg\n");
|
|
#endif
|
|
|
|
|
|
}
|
|
|
|
static msg_t *build_suspend_reject (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
|
|
{
|
|
msg_t *msg =(msg_t*)create_l3msg(CC_SUSPEND_REJECT | REQUEST, MT_SUSPEND_REJECT, bc?bc->l3_id:-1, sizeof(SUSPEND_REJECT_t) ,nt);
|
|
|
|
#ifdef DEBUG
|
|
printf("Building SUSPEND_REJECT Msg\n");
|
|
#endif
|
|
return msg;
|
|
}
|
|
|
|
static void parse_resume_reject (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("Parsing RESUME_REJECT Msg\n");
|
|
#endif
|
|
|
|
|
|
}
|
|
|
|
static msg_t *build_resume_reject (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
|
|
{
|
|
msg_t *msg =(msg_t*)create_l3msg(CC_RESUME_REJECT | REQUEST, MT_RESUME_REJECT, bc?bc->l3_id:-1, sizeof(RESUME_REJECT_t) ,nt);
|
|
|
|
#ifdef DEBUG
|
|
printf("Building RESUME_REJECT Msg\n");
|
|
#endif
|
|
return msg;
|
|
}
|
|
|
|
static void parse_hold (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("Parsing HOLD Msg\n");
|
|
#endif
|
|
|
|
|
|
}
|
|
|
|
static msg_t *build_hold (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
|
|
{
|
|
msg_t *msg =(msg_t*)create_l3msg(CC_HOLD | REQUEST, MT_HOLD, bc?bc->l3_id:-1, sizeof(HOLD_t) ,nt);
|
|
|
|
#ifdef DEBUG
|
|
printf("Building HOLD Msg\n");
|
|
#endif
|
|
return msg;
|
|
}
|
|
|
|
static void parse_suspend (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("Parsing SUSPEND Msg\n");
|
|
#endif
|
|
|
|
|
|
}
|
|
|
|
static msg_t *build_suspend (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
|
|
{
|
|
msg_t *msg =(msg_t*)create_l3msg(CC_SUSPEND | REQUEST, MT_SUSPEND, bc?bc->l3_id:-1, sizeof(SUSPEND_t) ,nt);
|
|
|
|
#ifdef DEBUG
|
|
printf("Building SUSPEND Msg\n");
|
|
#endif
|
|
return msg;
|
|
}
|
|
|
|
static void parse_resume (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("Parsing RESUME Msg\n");
|
|
#endif
|
|
|
|
|
|
}
|
|
|
|
static msg_t *build_resume (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
|
|
{
|
|
msg_t *msg =(msg_t*)create_l3msg(CC_RESUME | REQUEST, MT_RESUME, bc?bc->l3_id:-1, sizeof(RESUME_t) ,nt);
|
|
|
|
#ifdef DEBUG
|
|
printf("Building RESUME Msg\n");
|
|
#endif
|
|
return msg;
|
|
}
|
|
|
|
static void parse_hold_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("Parsing HOLD_ACKNOWLEDGE Msg\n");
|
|
#endif
|
|
|
|
|
|
}
|
|
|
|
static msg_t *build_hold_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
|
|
{
|
|
msg_t *msg =(msg_t*)create_l3msg(CC_HOLD_ACKNOWLEDGE | REQUEST, MT_HOLD_ACKNOWLEDGE, bc?bc->l3_id:-1, sizeof(HOLD_ACKNOWLEDGE_t) ,nt);
|
|
|
|
#ifdef DEBUG
|
|
printf("Building HOLD_ACKNOWLEDGE Msg\n");
|
|
#endif
|
|
return msg;
|
|
}
|
|
|
|
static void parse_suspend_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("Parsing SUSPEND_ACKNOWLEDGE Msg\n");
|
|
#endif
|
|
|
|
|
|
}
|
|
|
|
static msg_t *build_suspend_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
|
|
{
|
|
msg_t *msg =(msg_t*)create_l3msg(CC_SUSPEND_ACKNOWLEDGE | REQUEST, MT_SUSPEND_ACKNOWLEDGE, bc?bc->l3_id:-1, sizeof(SUSPEND_ACKNOWLEDGE_t) ,nt);
|
|
|
|
#ifdef DEBUG
|
|
printf("Building SUSPEND_ACKNOWLEDGE Msg\n");
|
|
#endif
|
|
return msg;
|
|
}
|
|
|
|
static void parse_resume_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("Parsing RESUME_ACKNOWLEDGE Msg\n");
|
|
#endif
|
|
|
|
|
|
}
|
|
|
|
static msg_t *build_resume_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
|
|
{
|
|
msg_t *msg =(msg_t*)create_l3msg(CC_RESUME_ACKNOWLEDGE | REQUEST, MT_RESUME_ACKNOWLEDGE, bc?bc->l3_id:-1, sizeof(RESUME_ACKNOWLEDGE_t) ,nt);
|
|
|
|
#ifdef DEBUG
|
|
printf("Building RESUME_ACKNOWLEDGE Msg\n");
|
|
#endif
|
|
return msg;
|
|
}
|
|
|
|
static void parse_hold_reject (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("Parsing HOLD_REJECT Msg\n");
|
|
#endif
|
|
|
|
|
|
}
|
|
|
|
static msg_t *build_hold_reject (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
|
|
{
|
|
msg_t *msg =(msg_t*)create_l3msg(CC_HOLD_REJECT | REQUEST, MT_HOLD_REJECT, bc?bc->l3_id:-1, sizeof(HOLD_REJECT_t) ,nt);
|
|
|
|
#ifdef DEBUG
|
|
printf("Building HOLD_REJECT Msg\n");
|
|
#endif
|
|
return msg;
|
|
}
|
|
|
|
static void parse_retrieve (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("Parsing RETRIEVE Msg\n");
|
|
#endif
|
|
|
|
|
|
}
|
|
|
|
static msg_t *build_retrieve (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
|
|
{
|
|
msg_t *msg =(msg_t*)create_l3msg(CC_RETRIEVE | REQUEST, MT_RETRIEVE, bc?bc->l3_id:-1, sizeof(RETRIEVE_t) ,nt);
|
|
|
|
#ifdef DEBUG
|
|
printf("Building RETRIEVE Msg\n");
|
|
#endif
|
|
return msg;
|
|
}
|
|
|
|
static void parse_retrieve_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("Parsing RETRIEVE_ACKNOWLEDGE Msg\n");
|
|
#endif
|
|
|
|
|
|
}
|
|
|
|
static msg_t *build_retrieve_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
|
|
{
|
|
int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
|
|
RETRIEVE_ACKNOWLEDGE_t *retrieve_acknowledge;
|
|
msg_t *msg =(msg_t*)create_l3msg(CC_RETRIEVE_ACKNOWLEDGE | REQUEST, MT_RETRIEVE_ACKNOWLEDGE, bc?bc->l3_id:-1, sizeof(RETRIEVE_ACKNOWLEDGE_t) ,nt);
|
|
|
|
retrieve_acknowledge=(RETRIEVE_ACKNOWLEDGE_t*)((msg->data+HEADER_LEN));
|
|
|
|
enc_ie_channel_id(&retrieve_acknowledge->CHANNEL_ID, msg, 1, bc->channel, nt,bc);
|
|
#ifdef DEBUG
|
|
printf("Building RETRIEVE_ACKNOWLEDGE Msg\n");
|
|
#endif
|
|
return msg;
|
|
}
|
|
|
|
static void parse_retrieve_reject (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("Parsing RETRIEVE_REJECT Msg\n");
|
|
#endif
|
|
|
|
|
|
}
|
|
|
|
static msg_t *build_retrieve_reject (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
|
|
{
|
|
msg_t *msg =(msg_t*)create_l3msg(CC_RETRIEVE_REJECT | REQUEST, MT_RETRIEVE_REJECT, bc?bc->l3_id:-1, sizeof(RETRIEVE_REJECT_t) ,nt);
|
|
|
|
#ifdef DEBUG
|
|
printf("Building RETRIEVE_REJECT Msg\n");
|
|
#endif
|
|
return msg;
|
|
}
|
|
|
|
static void parse_disconnect (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
|
|
{
|
|
int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
|
|
DISCONNECT_t *disconnect = (DISCONNECT_t *) (msg->data + HEADER_LEN);
|
|
int location;
|
|
int cause;
|
|
dec_ie_cause(disconnect->CAUSE, (Q931_info_t *)(disconnect), &location, &cause, nt,bc);
|
|
if (cause>0) bc->cause=cause;
|
|
|
|
dec_ie_facility(disconnect->FACILITY, (Q931_info_t *) disconnect, &bc->fac_in, nt, bc);
|
|
|
|
dec_ie_progress(disconnect->PROGRESS, (Q931_info_t *)disconnect, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc);
|
|
#ifdef DEBUG
|
|
printf("Parsing DISCONNECT Msg\n");
|
|
#endif
|
|
|
|
|
|
}
|
|
|
|
static msg_t *build_disconnect (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
|
|
{
|
|
int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
|
|
DISCONNECT_t *disconnect;
|
|
msg_t *msg =(msg_t*)create_l3msg(CC_DISCONNECT | REQUEST, MT_DISCONNECT, bc?bc->l3_id:-1, sizeof(DISCONNECT_t) ,nt);
|
|
|
|
disconnect=(DISCONNECT_t*)((msg->data+HEADER_LEN));
|
|
|
|
enc_ie_cause(&disconnect->CAUSE, msg, (nt)?1:0, bc->out_cause,nt,bc);
|
|
if (nt) {
|
|
enc_ie_progress(&disconnect->PROGRESS, msg, 0, nt ? 1 : 5, 8, nt, bc);
|
|
}
|
|
|
|
if (bc->fac_out.Function != Fac_None) {
|
|
enc_ie_facility(&disconnect->FACILITY, msg, &bc->fac_out, nt);
|
|
}
|
|
|
|
if (bc->uulen) {
|
|
int protocol=4;
|
|
enc_ie_useruser(&disconnect->USER_USER, msg, protocol, bc->uu, bc->uulen, nt,bc);
|
|
cb_log(1,bc->port,"ENCODING USERUESRINFO:%s\n",bc->uu);
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
printf("Building DISCONNECT Msg\n");
|
|
#endif
|
|
return msg;
|
|
}
|
|
|
|
static void parse_restart (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
|
|
{
|
|
int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
|
|
RESTART_t *restart = (RESTART_t *) (msg->data + HEADER_LEN);
|
|
|
|
struct misdn_stack *stack=get_stack_by_bc(bc);
|
|
|
|
#ifdef DEBUG
|
|
printf("Parsing RESTART Msg\n");
|
|
#endif
|
|
|
|
{
|
|
int exclusive;
|
|
dec_ie_channel_id(restart->CHANNEL_ID, (Q931_info_t *)restart, &exclusive, &bc->restart_channel, nt,bc);
|
|
cb_log(3, stack->port, "CC_RESTART Request on channel:%d on this port.\n", bc->restart_channel);
|
|
}
|
|
|
|
}
|
|
|
|
static msg_t *build_restart (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
|
|
{
|
|
int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
|
|
RESTART_t *restart;
|
|
msg_t *msg =(msg_t*)create_l3msg(CC_RESTART | REQUEST, MT_RESTART, bc?bc->l3_id:-1, sizeof(RESTART_t) ,nt);
|
|
|
|
restart=(RESTART_t*)((msg->data+HEADER_LEN));
|
|
|
|
#ifdef DEBUG
|
|
printf("Building RESTART Msg\n");
|
|
#endif
|
|
|
|
if (bc->channel > 0) {
|
|
enc_ie_channel_id(&restart->CHANNEL_ID, msg, 1,bc->channel, nt,bc);
|
|
enc_ie_restart_ind(&restart->RESTART_IND, msg, 0x80, nt, bc);
|
|
} else {
|
|
enc_ie_restart_ind(&restart->RESTART_IND, msg, 0x87, nt, bc);
|
|
}
|
|
|
|
cb_log(0,bc->port, "Restarting channel %d\n", bc->channel);
|
|
return msg;
|
|
}
|
|
|
|
static void parse_release (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
|
|
{
|
|
int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
|
|
RELEASE_t *release = (RELEASE_t *) (msg->data + HEADER_LEN);
|
|
int location;
|
|
int cause;
|
|
|
|
dec_ie_cause(release->CAUSE, (Q931_info_t *)(release), &location, &cause, nt,bc);
|
|
if (cause>0) bc->cause=cause;
|
|
|
|
dec_ie_facility(release->FACILITY, (Q931_info_t *) release, &bc->fac_in, nt, bc);
|
|
|
|
#ifdef DEBUG
|
|
printf("Parsing RELEASE Msg\n");
|
|
#endif
|
|
|
|
|
|
}
|
|
|
|
static msg_t *build_release (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
|
|
{
|
|
int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
|
|
RELEASE_t *release;
|
|
msg_t *msg =(msg_t*)create_l3msg(CC_RELEASE | REQUEST, MT_RELEASE, bc?bc->l3_id:-1, sizeof(RELEASE_t) ,nt);
|
|
|
|
release=(RELEASE_t*)((msg->data+HEADER_LEN));
|
|
|
|
if (bc->out_cause>= 0)
|
|
enc_ie_cause(&release->CAUSE, msg, nt?1:0, bc->out_cause, nt,bc);
|
|
|
|
if (bc->fac_out.Function != Fac_None) {
|
|
enc_ie_facility(&release->FACILITY, msg, &bc->fac_out, nt);
|
|
}
|
|
|
|
if (bc->uulen) {
|
|
int protocol=4;
|
|
enc_ie_useruser(&release->USER_USER, msg, protocol, bc->uu, bc->uulen, nt,bc);
|
|
cb_log(1,bc->port,"ENCODING USERUESRINFO:%s\n",bc->uu);
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
printf("Building RELEASE Msg\n");
|
|
#endif
|
|
return msg;
|
|
}
|
|
|
|
static void parse_release_complete (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
|
|
{
|
|
int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
|
|
RELEASE_COMPLETE_t *release_complete = (RELEASE_COMPLETE_t *) (msg->data + HEADER_LEN);
|
|
int location;
|
|
int cause;
|
|
iframe_t *frm = (iframe_t*) msg->data;
|
|
|
|
struct misdn_stack *stack=get_stack_by_bc(bc);
|
|
mISDNuser_head_t *hh;
|
|
hh=(mISDNuser_head_t*)msg->data;
|
|
|
|
/*hh=(mISDN_head_t*)msg->data;
|
|
mISDN_head_t *hh;*/
|
|
|
|
if (nt) {
|
|
if (hh->prim == (CC_RELEASE_COMPLETE|CONFIRM)) {
|
|
cb_log(0, stack->port, "CC_RELEASE_COMPLETE|CONFIRM [NT] \n");
|
|
return;
|
|
}
|
|
} else {
|
|
if (frm->prim == (CC_RELEASE_COMPLETE|CONFIRM)) {
|
|
cb_log(0, stack->port, "CC_RELEASE_COMPLETE|CONFIRM [TE] \n");
|
|
return;
|
|
}
|
|
}
|
|
dec_ie_cause(release_complete->CAUSE, (Q931_info_t *)(release_complete), &location, &cause, nt,bc);
|
|
if (cause>0) bc->cause=cause;
|
|
|
|
dec_ie_facility(release_complete->FACILITY, (Q931_info_t *) release_complete, &bc->fac_in, nt, bc);
|
|
|
|
#ifdef DEBUG
|
|
printf("Parsing RELEASE_COMPLETE Msg\n");
|
|
#endif
|
|
}
|
|
|
|
static msg_t *build_release_complete (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
|
|
{
|
|
int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
|
|
RELEASE_COMPLETE_t *release_complete;
|
|
msg_t *msg =(msg_t*)create_l3msg(CC_RELEASE_COMPLETE | REQUEST, MT_RELEASE_COMPLETE, bc?bc->l3_id:-1, sizeof(RELEASE_COMPLETE_t) ,nt);
|
|
|
|
release_complete=(RELEASE_COMPLETE_t*)((msg->data+HEADER_LEN));
|
|
|
|
enc_ie_cause(&release_complete->CAUSE, msg, nt?1:0, bc->out_cause, nt,bc);
|
|
|
|
if (bc->fac_out.Function != Fac_None) {
|
|
enc_ie_facility(&release_complete->FACILITY, msg, &bc->fac_out, nt);
|
|
}
|
|
|
|
if (bc->uulen) {
|
|
int protocol=4;
|
|
enc_ie_useruser(&release_complete->USER_USER, msg, protocol, bc->uu, bc->uulen, nt,bc);
|
|
cb_log(1,bc->port,"ENCODING USERUESRINFO:%s\n",bc->uu);
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
printf("Building RELEASE_COMPLETE Msg\n");
|
|
#endif
|
|
return msg;
|
|
}
|
|
|
|
static void parse_facility (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
|
|
{
|
|
int HEADER_LEN = nt ? mISDNUSER_HEAD_SIZE : mISDN_HEADER_LEN;
|
|
FACILITY_t *facility = (FACILITY_t*)(msg->data+HEADER_LEN);
|
|
Q931_info_t *qi = (Q931_info_t*)(msg->data+HEADER_LEN);
|
|
unsigned char *p = NULL;
|
|
#if defined(AST_MISDN_ENHANCEMENTS)
|
|
int description_code;
|
|
int type;
|
|
int plan;
|
|
int present;
|
|
char number[sizeof(bc->redirecting.to.number)];
|
|
#endif /* defined(AST_MISDN_ENHANCEMENTS) */
|
|
|
|
#ifdef DEBUG
|
|
printf("Parsing FACILITY Msg\n");
|
|
#endif
|
|
|
|
bc->fac_in.Function = Fac_None;
|
|
|
|
if (!bc->nt) {
|
|
if (qi->QI_ELEMENT(facility))
|
|
p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(facility) + 1;
|
|
} else {
|
|
p = facility->FACILITY;
|
|
}
|
|
if (!p)
|
|
return;
|
|
|
|
if (decodeFac(p, &bc->fac_in)) {
|
|
cb_log(3, bc->port, "Decoding facility ie failed! Unrecognized facility message?\n");
|
|
}
|
|
|
|
#if defined(AST_MISDN_ENHANCEMENTS)
|
|
dec_ie_notify(facility->NOTIFY, qi, &description_code, nt, bc);
|
|
if (description_code < 0) {
|
|
bc->notify_description_code = mISDN_NOTIFY_CODE_INVALID;
|
|
} else {
|
|
bc->notify_description_code = description_code;
|
|
}
|
|
|
|
dec_ie_redir_dn(facility->REDIR_DN, qi, &type, &plan, &present, number, sizeof(number), nt, bc);
|
|
if (0 <= type) {
|
|
bc->redirecting.to_changed = 1;
|
|
|
|
bc->redirecting.to.number_type = type;
|
|
bc->redirecting.to.number_plan = plan;
|
|
switch (present) {
|
|
default:
|
|
case 0:
|
|
bc->redirecting.to.presentation = 0; /* presentation allowed */
|
|
break;
|
|
case 1:
|
|
bc->redirecting.to.presentation = 1; /* presentation restricted */
|
|
break;
|
|
case 2:
|
|
bc->redirecting.to.presentation = 2; /* Number not available */
|
|
break;
|
|
}
|
|
bc->redirecting.to.screening = 0; /* Unscreened */
|
|
strcpy(bc->redirecting.to.number, number);
|
|
}
|
|
#endif /* defined(AST_MISDN_ENHANCEMENTS) */
|
|
}
|
|
|
|
static msg_t *build_facility (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
|
|
{
|
|
int len;
|
|
int HEADER_LEN;
|
|
unsigned char *ie_fac;
|
|
unsigned char fac_tmp[256];
|
|
msg_t *msg;
|
|
FACILITY_t *facility;
|
|
Q931_info_t *qi;
|
|
|
|
#ifdef DEBUG
|
|
printf("Building FACILITY Msg\n");
|
|
#endif
|
|
|
|
len = encodeFac(fac_tmp, &(bc->fac_out));
|
|
if (len <= 0) {
|
|
/*
|
|
* mISDN does not know how to build the requested facility structure
|
|
* Clear facility information
|
|
*/
|
|
bc->fac_out.Function = Fac_None;
|
|
|
|
#if defined(AST_MISDN_ENHANCEMENTS)
|
|
/* Clear other one shot information. */
|
|
bc->notify_description_code = mISDN_NOTIFY_CODE_INVALID;
|
|
bc->redirecting.to_changed = 0;
|
|
#endif /* defined(AST_MISDN_ENHANCEMENTS) */
|
|
return NULL;
|
|
}
|
|
|
|
msg = (msg_t *) create_l3msg(CC_FACILITY | REQUEST, MT_FACILITY, bc ? bc->l3_id : -1, sizeof(FACILITY_t), nt);
|
|
HEADER_LEN = nt ? mISDNUSER_HEAD_SIZE : mISDN_HEADER_LEN;
|
|
facility = (FACILITY_t *) (msg->data + HEADER_LEN);
|
|
|
|
ie_fac = msg_put(msg, len);
|
|
if (bc->nt) {
|
|
facility->FACILITY = ie_fac + 1;
|
|
} else {
|
|
qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
|
|
qi->QI_ELEMENT(facility) = ie_fac - (unsigned char *)qi - sizeof(Q931_info_t);
|
|
}
|
|
|
|
memcpy(ie_fac, fac_tmp, len);
|
|
|
|
/* Clear facility information */
|
|
bc->fac_out.Function = Fac_None;
|
|
|
|
if (*bc->display) {
|
|
#ifdef DEBUG
|
|
printf("Sending %s as Display\n", bc->display);
|
|
#endif
|
|
enc_ie_display(&facility->DISPLAY, msg, bc->display, nt,bc);
|
|
}
|
|
|
|
#if defined(AST_MISDN_ENHANCEMENTS)
|
|
if (bc->notify_description_code != mISDN_NOTIFY_CODE_INVALID) {
|
|
enc_ie_notify(&facility->NOTIFY, msg, bc->notify_description_code, nt, bc);
|
|
bc->notify_description_code = mISDN_NOTIFY_CODE_INVALID;
|
|
}
|
|
|
|
if (bc->redirecting.to_changed) {
|
|
bc->redirecting.to_changed = 0;
|
|
switch (bc->outgoing_colp) {
|
|
case 0:/* pass */
|
|
case 1:/* restricted */
|
|
enc_ie_redir_dn(&facility->REDIR_DN, msg, bc->redirecting.to.number_type,
|
|
bc->redirecting.to.number_plan, bc->redirecting.to.presentation,
|
|
bc->redirecting.to.number, nt, bc);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
#endif /* defined(AST_MISDN_ENHANCEMENTS) */
|
|
|
|
return msg;
|
|
}
|
|
|
|
#if defined(AST_MISDN_ENHANCEMENTS)
|
|
/*!
|
|
* \internal
|
|
* \brief Parse a received REGISTER message
|
|
*
|
|
* \param msgs Search table entry that called us.
|
|
* \param msg Received message contents
|
|
* \param bc Associated B channel
|
|
* \param nt TRUE if in NT mode.
|
|
*
|
|
* \return Nothing
|
|
*/
|
|
static void parse_register(struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
|
|
{
|
|
int HEADER_LEN;
|
|
REGISTER_t *reg;
|
|
|
|
HEADER_LEN = nt ? mISDNUSER_HEAD_SIZE : mISDN_HEADER_LEN;
|
|
reg = (REGISTER_t *) (msg->data + HEADER_LEN);
|
|
|
|
/*
|
|
* A facility ie is optional.
|
|
* The peer may just be establishing a connection to send
|
|
* messages later.
|
|
*/
|
|
dec_ie_facility(reg->FACILITY, (Q931_info_t *) reg, &bc->fac_in, nt, bc);
|
|
}
|
|
#endif /* defined(AST_MISDN_ENHANCEMENTS) */
|
|
|
|
#if defined(AST_MISDN_ENHANCEMENTS)
|
|
/*!
|
|
* \internal
|
|
* \brief Construct a REGISTER message
|
|
*
|
|
* \param msgs Search table entry that called us.
|
|
* \param bc Associated B channel
|
|
* \param nt TRUE if in NT mode.
|
|
*
|
|
* \return Allocated built message
|
|
*/
|
|
static msg_t *build_register(struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
|
|
{
|
|
int HEADER_LEN;
|
|
REGISTER_t *reg;
|
|
msg_t *msg;
|
|
|
|
msg = (msg_t *) create_l3msg(CC_REGISTER | REQUEST, MT_REGISTER, bc ? bc->l3_id : -1, sizeof(REGISTER_t), nt);
|
|
HEADER_LEN = nt ? mISDNUSER_HEAD_SIZE : mISDN_HEADER_LEN;
|
|
reg = (REGISTER_t *) (msg->data + HEADER_LEN);
|
|
|
|
if (bc->fac_out.Function != Fac_None) {
|
|
enc_ie_facility(®->FACILITY, msg, &bc->fac_out, nt);
|
|
}
|
|
|
|
return msg;
|
|
}
|
|
#endif /* defined(AST_MISDN_ENHANCEMENTS) */
|
|
|
|
static void parse_notify (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
|
|
{
|
|
int HEADER_LEN = nt ? mISDNUSER_HEAD_SIZE : mISDN_HEADER_LEN;
|
|
NOTIFY_t *notify = (NOTIFY_t *) (msg->data + HEADER_LEN);
|
|
int description_code;
|
|
int type;
|
|
int plan;
|
|
int present;
|
|
char number[sizeof(bc->redirecting.to.number)];
|
|
|
|
#ifdef DEBUG
|
|
printf("Parsing NOTIFY Msg\n");
|
|
#endif
|
|
|
|
dec_ie_notify(notify->NOTIFY, (Q931_info_t *) notify, &description_code, nt, bc);
|
|
if (description_code < 0) {
|
|
bc->notify_description_code = mISDN_NOTIFY_CODE_INVALID;
|
|
} else {
|
|
bc->notify_description_code = description_code;
|
|
}
|
|
|
|
dec_ie_redir_dn(notify->REDIR_DN, (Q931_info_t *) notify, &type, &plan, &present, number, sizeof(number), nt, bc);
|
|
if (0 <= type) {
|
|
bc->redirecting.to_changed = 1;
|
|
|
|
bc->redirecting.to.number_type = type;
|
|
bc->redirecting.to.number_plan = plan;
|
|
switch (present) {
|
|
default:
|
|
case 0:
|
|
bc->redirecting.to.presentation = 0; /* presentation allowed */
|
|
break;
|
|
case 1:
|
|
bc->redirecting.to.presentation = 1; /* presentation restricted */
|
|
break;
|
|
case 2:
|
|
bc->redirecting.to.presentation = 2; /* Number not available */
|
|
break;
|
|
}
|
|
bc->redirecting.to.screening = 0; /* Unscreened */
|
|
strcpy(bc->redirecting.to.number, number);
|
|
}
|
|
}
|
|
|
|
static msg_t *build_notify (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
|
|
{
|
|
int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
|
|
NOTIFY_t *notify;
|
|
msg_t *msg =(msg_t*)create_l3msg(CC_NOTIFY | REQUEST, MT_NOTIFY, bc?bc->l3_id:-1, sizeof(NOTIFY_t) ,nt);
|
|
|
|
#ifdef DEBUG
|
|
printf("Building NOTIFY Msg\n");
|
|
#endif
|
|
|
|
notify = (NOTIFY_t *) (msg->data + HEADER_LEN);
|
|
|
|
enc_ie_notify(¬ify->NOTIFY, msg, bc->notify_description_code, nt, bc);
|
|
bc->notify_description_code = mISDN_NOTIFY_CODE_INVALID;
|
|
|
|
if (bc->redirecting.to_changed) {
|
|
bc->redirecting.to_changed = 0;
|
|
switch (bc->outgoing_colp) {
|
|
case 0:/* pass */
|
|
case 1:/* restricted */
|
|
enc_ie_redir_dn(¬ify->REDIR_DN, msg, bc->redirecting.to.number_type,
|
|
bc->redirecting.to.number_plan, bc->redirecting.to.presentation,
|
|
bc->redirecting.to.number, nt, bc);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
return msg;
|
|
}
|
|
|
|
static void parse_status_enquiry (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("Parsing STATUS_ENQUIRY Msg\n");
|
|
#endif
|
|
}
|
|
|
|
static msg_t *build_status_enquiry (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
|
|
{
|
|
msg_t *msg =(msg_t*)create_l3msg(CC_STATUS_ENQUIRY | REQUEST, MT_STATUS_ENQUIRY, bc?bc->l3_id:-1, sizeof(STATUS_ENQUIRY_t) ,nt);
|
|
|
|
#ifdef DEBUG
|
|
printf("Building STATUS_ENQUIRY Msg\n");
|
|
#endif
|
|
return msg;
|
|
}
|
|
|
|
static void parse_information (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
|
|
{
|
|
int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
|
|
INFORMATION_t *information = (INFORMATION_t *) (msg->data + HEADER_LEN);
|
|
int type, plan;
|
|
|
|
dec_ie_called_pn(information->CALLED_PN, (Q931_info_t *) information, &type, &plan, bc->info_dad, sizeof(bc->info_dad), nt, bc);
|
|
dec_ie_keypad(information->KEYPAD, (Q931_info_t *) information, bc->keypad, sizeof(bc->keypad), nt, bc);
|
|
|
|
#ifdef DEBUG
|
|
printf("Parsing INFORMATION Msg\n");
|
|
#endif
|
|
}
|
|
|
|
static msg_t *build_information (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
|
|
{
|
|
int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
|
|
INFORMATION_t *information;
|
|
msg_t *msg =(msg_t*)create_l3msg(CC_INFORMATION | REQUEST, MT_INFORMATION, bc?bc->l3_id:-1, sizeof(INFORMATION_t) ,nt);
|
|
|
|
information=(INFORMATION_t*)((msg->data+HEADER_LEN));
|
|
|
|
enc_ie_called_pn(&information->CALLED_PN, msg, 0, 1, bc->info_dad, nt,bc);
|
|
|
|
{
|
|
if (*bc->display) {
|
|
#ifdef DEBUG
|
|
printf("Sending %s as Display\n", bc->display);
|
|
#endif
|
|
enc_ie_display(&information->DISPLAY, msg, bc->display, nt,bc);
|
|
}
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
printf("Building INFORMATION Msg\n");
|
|
#endif
|
|
return msg;
|
|
}
|
|
|
|
static void parse_status (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
|
|
{
|
|
int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
|
|
STATUS_t *status = (STATUS_t *) (msg->data + HEADER_LEN);
|
|
int location;
|
|
int cause;
|
|
|
|
dec_ie_cause(status->CAUSE, (Q931_info_t *)(status), &location, &cause, nt,bc);
|
|
if (cause>0) bc->cause=cause;
|
|
|
|
#ifdef DEBUG
|
|
printf("Parsing STATUS Msg\n");
|
|
#endif
|
|
}
|
|
|
|
static msg_t *build_status (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
|
|
{
|
|
msg_t *msg =(msg_t*)create_l3msg(CC_STATUS | REQUEST, MT_STATUS, bc?bc->l3_id:-1, sizeof(STATUS_t) ,nt);
|
|
|
|
#ifdef DEBUG
|
|
printf("Building STATUS Msg\n");
|
|
#endif
|
|
return msg;
|
|
}
|
|
|
|
static void parse_timeout (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("Parsing STATUS Msg\n");
|
|
#endif
|
|
}
|
|
|
|
static msg_t *build_timeout (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
|
|
{
|
|
msg_t *msg =(msg_t*)create_l3msg(CC_STATUS | REQUEST, MT_STATUS, bc?bc->l3_id:-1, sizeof(STATUS_t) ,nt);
|
|
|
|
#ifdef DEBUG
|
|
printf("Building STATUS Msg\n");
|
|
#endif
|
|
return msg;
|
|
}
|
|
|
|
|
|
/************************************/
|
|
|
|
|
|
|
|
|
|
/** Msg Array **/
|
|
|
|
struct isdn_msg msgs_g[] = {
|
|
/* *INDENT-OFF* */
|
|
/* misdn_msg, event, msg_parser, msg_builder, info */
|
|
{ CC_PROCEEDING, EVENT_PROCEEDING, parse_proceeding, build_proceeding, "PROCEEDING" },
|
|
{ CC_ALERTING, EVENT_ALERTING, parse_alerting, build_alerting, "ALERTING" },
|
|
{ CC_PROGRESS, EVENT_PROGRESS, parse_progress, build_progress, "PROGRESS" },
|
|
{ CC_SETUP, EVENT_SETUP, parse_setup, build_setup, "SETUP" },
|
|
#if defined(AST_MISDN_ENHANCEMENTS)
|
|
{ CC_REGISTER, EVENT_REGISTER, parse_register, build_register, "REGISTER" },
|
|
#endif /* defined(AST_MISDN_ENHANCEMENTS) */
|
|
{ CC_CONNECT, EVENT_CONNECT, parse_connect, build_connect, "CONNECT" },
|
|
{ CC_SETUP_ACKNOWLEDGE, EVENT_SETUP_ACKNOWLEDGE, parse_setup_acknowledge, build_setup_acknowledge, "SETUP_ACKNOWLEDGE" },
|
|
{ CC_CONNECT_ACKNOWLEDGE, EVENT_CONNECT_ACKNOWLEDGE, parse_connect_acknowledge, build_connect_acknowledge, "CONNECT_ACKNOWLEDGE " },
|
|
{ CC_USER_INFORMATION, EVENT_USER_INFORMATION, parse_user_information, build_user_information, "USER_INFORMATION" },
|
|
{ CC_SUSPEND_REJECT, EVENT_SUSPEND_REJECT, parse_suspend_reject, build_suspend_reject, "SUSPEND_REJECT" },
|
|
{ CC_RESUME_REJECT, EVENT_RESUME_REJECT, parse_resume_reject, build_resume_reject, "RESUME_REJECT" },
|
|
{ CC_HOLD, EVENT_HOLD, parse_hold, build_hold, "HOLD" },
|
|
{ CC_SUSPEND, EVENT_SUSPEND, parse_suspend, build_suspend, "SUSPEND" },
|
|
{ CC_RESUME, EVENT_RESUME, parse_resume, build_resume, "RESUME" },
|
|
{ CC_HOLD_ACKNOWLEDGE, EVENT_HOLD_ACKNOWLEDGE, parse_hold_acknowledge, build_hold_acknowledge, "HOLD_ACKNOWLEDGE" },
|
|
{ CC_SUSPEND_ACKNOWLEDGE, EVENT_SUSPEND_ACKNOWLEDGE, parse_suspend_acknowledge, build_suspend_acknowledge, "SUSPEND_ACKNOWLEDGE" },
|
|
{ CC_RESUME_ACKNOWLEDGE, EVENT_RESUME_ACKNOWLEDGE, parse_resume_acknowledge, build_resume_acknowledge, "RESUME_ACKNOWLEDGE" },
|
|
{ CC_HOLD_REJECT, EVENT_HOLD_REJECT, parse_hold_reject, build_hold_reject, "HOLD_REJECT" },
|
|
{ CC_RETRIEVE, EVENT_RETRIEVE, parse_retrieve, build_retrieve, "RETRIEVE" },
|
|
{ CC_RETRIEVE_ACKNOWLEDGE, EVENT_RETRIEVE_ACKNOWLEDGE, parse_retrieve_acknowledge, build_retrieve_acknowledge, "RETRIEVE_ACKNOWLEDGE" },
|
|
{ CC_RETRIEVE_REJECT, EVENT_RETRIEVE_REJECT, parse_retrieve_reject, build_retrieve_reject, "RETRIEVE_REJECT" },
|
|
{ CC_DISCONNECT, EVENT_DISCONNECT, parse_disconnect, build_disconnect, "DISCONNECT" },
|
|
{ CC_RESTART, EVENT_RESTART, parse_restart, build_restart, "RESTART" },
|
|
{ CC_RELEASE, EVENT_RELEASE, parse_release, build_release, "RELEASE" },
|
|
{ CC_RELEASE_COMPLETE, EVENT_RELEASE_COMPLETE, parse_release_complete, build_release_complete, "RELEASE_COMPLETE" },
|
|
{ CC_FACILITY, EVENT_FACILITY, parse_facility, build_facility, "FACILITY" },
|
|
{ CC_NOTIFY, EVENT_NOTIFY, parse_notify, build_notify, "NOTIFY" },
|
|
{ CC_STATUS_ENQUIRY, EVENT_STATUS_ENQUIRY, parse_status_enquiry, build_status_enquiry, "STATUS_ENQUIRY" },
|
|
{ CC_INFORMATION, EVENT_INFORMATION, parse_information, build_information, "INFORMATION" },
|
|
{ CC_STATUS, EVENT_STATUS, parse_status, build_status, "STATUS" },
|
|
{ CC_TIMEOUT, EVENT_TIMEOUT, parse_timeout, build_timeout, "TIMEOUT" },
|
|
{ 0, 0, NULL, NULL, NULL }
|
|
/* *INDENT-ON* */
|
|
};
|
|
|
|
#define msgs_max (sizeof(msgs_g)/sizeof(struct isdn_msg))
|
|
|
|
/** INTERFACE FCTS ***/
|
|
int isdn_msg_get_index(struct isdn_msg msgs[], msg_t *msg, int nt)
|
|
{
|
|
int i;
|
|
|
|
if (nt){
|
|
mISDNuser_head_t *hh = (mISDNuser_head_t*)msg->data;
|
|
|
|
for (i=0; i< msgs_max -1; i++) {
|
|
if ( (hh->prim&COMMAND_MASK)==(msgs[i].misdn_msg&COMMAND_MASK)) return i;
|
|
}
|
|
|
|
} else {
|
|
iframe_t *frm = (iframe_t*)msg->data;
|
|
|
|
for (i=0; i< msgs_max -1; i++)
|
|
if ( (frm->prim&COMMAND_MASK)==(msgs[i].misdn_msg&COMMAND_MASK)) return i;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
int isdn_msg_get_index_by_event(struct isdn_msg msgs[], enum event_e event, int nt)
|
|
{
|
|
int i;
|
|
for (i=0; i< msgs_max; i++)
|
|
if ( event == msgs[i].event) return i;
|
|
|
|
cb_log(10,0, "get_index: event not found!\n");
|
|
|
|
return -1;
|
|
}
|
|
|
|
enum event_e isdn_msg_get_event(struct isdn_msg msgs[], msg_t *msg, int nt)
|
|
{
|
|
int i=isdn_msg_get_index(msgs, msg, nt);
|
|
if(i>=0) return msgs[i].event;
|
|
return EVENT_UNKNOWN;
|
|
}
|
|
|
|
char * isdn_msg_get_info(struct isdn_msg msgs[], msg_t *msg, int nt)
|
|
{
|
|
int i=isdn_msg_get_index(msgs, msg, nt);
|
|
if(i>=0) return msgs[i].info;
|
|
return NULL;
|
|
}
|
|
|
|
|
|
char EVENT_CLEAN_INFO[] = "CLEAN_UP";
|
|
char EVENT_DTMF_TONE_INFO[] = "DTMF_TONE";
|
|
char EVENT_NEW_L3ID_INFO[] = "NEW_L3ID";
|
|
char EVENT_NEW_BC_INFO[] = "NEW_BC";
|
|
char EVENT_PORT_ALARM_INFO[] = "ALARM";
|
|
char EVENT_NEW_CHANNEL_INFO[] = "NEW_CHANNEL";
|
|
char EVENT_BCHAN_DATA_INFO[] = "BCHAN_DATA";
|
|
char EVENT_BCHAN_ACTIVATED_INFO[] = "BCHAN_ACTIVATED";
|
|
char EVENT_TONE_GENERATE_INFO[] = "TONE_GENERATE";
|
|
char EVENT_BCHAN_ERROR_INFO[] = "BCHAN_ERROR";
|
|
|
|
char * isdn_get_info(struct isdn_msg msgs[], enum event_e event, int nt)
|
|
{
|
|
int i=isdn_msg_get_index_by_event(msgs, event, nt);
|
|
|
|
if(i>=0) return msgs[i].info;
|
|
|
|
if (event == EVENT_CLEANUP) return EVENT_CLEAN_INFO;
|
|
if (event == EVENT_DTMF_TONE) return EVENT_DTMF_TONE_INFO;
|
|
if (event == EVENT_NEW_L3ID) return EVENT_NEW_L3ID_INFO;
|
|
if (event == EVENT_NEW_BC) return EVENT_NEW_BC_INFO;
|
|
if (event == EVENT_NEW_CHANNEL) return EVENT_NEW_CHANNEL_INFO;
|
|
if (event == EVENT_BCHAN_DATA) return EVENT_BCHAN_DATA_INFO;
|
|
if (event == EVENT_BCHAN_ACTIVATED) return EVENT_BCHAN_ACTIVATED_INFO;
|
|
if (event == EVENT_TONE_GENERATE) return EVENT_TONE_GENERATE_INFO;
|
|
if (event == EVENT_PORT_ALARM) return EVENT_PORT_ALARM_INFO;
|
|
if (event == EVENT_BCHAN_ERROR) return EVENT_BCHAN_ERROR_INFO;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
int isdn_msg_parse_event(struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
|
|
{
|
|
int i=isdn_msg_get_index(msgs, msg, nt);
|
|
if(i<0) return -1;
|
|
|
|
msgs[i].msg_parser(msgs, msg, bc, nt);
|
|
return 0;
|
|
}
|
|
|
|
msg_t * isdn_msg_build_event(struct isdn_msg msgs[], struct misdn_bchannel *bc, enum event_e event, int nt)
|
|
{
|
|
int i=isdn_msg_get_index_by_event(msgs, event, nt);
|
|
if(i<0) return NULL;
|
|
|
|
return msgs[i].msg_builder(msgs, bc, nt);
|
|
}
|