aboutsummaryrefslogtreecommitdiffstats
path: root/channels/misdn/isdn_msg_parser.c
diff options
context:
space:
mode:
authorrmudgett <rmudgett@f38db490-d61c-443f-a65b-d21fe96a405b>2009-04-21 17:44:01 +0000
committerrmudgett <rmudgett@f38db490-d61c-443f-a65b-d21fe96a405b>2009-04-21 17:44:01 +0000
commitfa490a06b5a883cef9a2bc61c1c302df9012f82e (patch)
tree274e051566d5d31050dc6c64f1ae79bc83bf38a5 /channels/misdn/isdn_msg_parser.c
parent69331f19c40cc890d77fa3e448182e6fb3450f65 (diff)
Added CCBS/CCNR Party A support and enhanced COLP support.
This change adds the following features to chan_misdn: * CCBS/CCNR Party A support for PTMP and PTP modes. * Enhances COLP support for call diversion and explicit call transfer. These enhanced features require a modified version of mISDN. The latest modified mISDN v1.1.x based version is available at: http://svn.digium.com/svn/thirdparty/mISDN/trunk http://svn.digium.com/svn/thirdparty/mISDNuser/trunk Taged versions of the modified mISDN code are available under: http://svn.digium.com/svn/thirdparty/mISDN/tags http://svn.digium.com/svn/thirdparty/mISDNuser/tags Review: http://reviewboard.digium.com/r/218/ Merged from team/rmudgett/misdn_facility branch. git-svn-id: http://svn.digium.com/svn/asterisk/trunk@189735 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channels/misdn/isdn_msg_parser.c')
-rw-r--r--channels/misdn/isdn_msg_parser.c394
1 files changed, 366 insertions, 28 deletions
diff --git a/channels/misdn/isdn_msg_parser.c b/channels/misdn/isdn_msg_parser.c
index 01c084ff7..4201cab2e 100644
--- a/channels/misdn/isdn_msg_parser.c
+++ b/channels/misdn/isdn_msg_parser.c
@@ -61,6 +61,80 @@ static void build_display_str(char *display, size_t display_length, int display_
}
}
+/*!
+ * \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)
{
@@ -93,7 +167,7 @@ static void set_channel(struct misdn_bchannel *bc, int channel)
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*)((unsigned long)msg->data+ HEADER_LEN);
+ CALL_PROCEEDING_t *proceeding = (CALL_PROCEEDING_t *) (msg->data + HEADER_LEN);
//struct misdn_stack *stack=get_stack_by_bc(bc);
{
@@ -106,6 +180,9 @@ static void parse_proceeding (struct isdn_msg msgs[], msg_t *msg, struct misdn_b
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");
@@ -124,6 +201,11 @@ static msg_t *build_proceeding (struct isdn_msg msgs[], struct misdn_bchannel *b
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");
@@ -134,9 +216,13 @@ static msg_t *build_proceeding (struct isdn_msg msgs[], struct misdn_bchannel *b
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*)((unsigned long)(msg->data+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
@@ -158,6 +244,13 @@ static msg_t *build_alerting (struct isdn_msg msgs[], struct misdn_bchannel *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
@@ -168,11 +261,13 @@ static msg_t *build_alerting (struct isdn_msg msgs[], struct misdn_bchannel *bc,
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*)((unsigned long)(msg->data+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
@@ -186,17 +281,92 @@ static msg_t *build_progress (struct isdn_msg msgs[], struct misdn_bchannel *bc,
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*)((unsigned long)msg->data+HEADER_LEN);
- Q931_info_t *qi=(Q931_info_t*)((unsigned long)msg->data+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;
@@ -207,7 +377,7 @@ static void parse_setup (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchann
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) - 1, nt, bc);
+ 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) {
@@ -228,15 +398,17 @@ static void parse_setup (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchann
bc->caller.screening = 0; /* Unscreened */
}
- dec_ie_called_pn(setup->CALLED_PN, (Q931_info_t *) setup, &type, &plan, bc->dialed.number, sizeof(bc->dialed.number) - 1, nt, bc);
+ 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) - 1, nt, bc);
+ 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) - 1, 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) {
@@ -317,6 +489,9 @@ static void parse_setup (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchann
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' */
@@ -333,6 +508,9 @@ static msg_t *build_setup (struct isdn_msg msgs[], struct misdn_bchannel *bc, in
else
enc_ie_channel_id(&setup->CHANNEL_ID, msg, 1, bc->channel, nt,bc);
+ if (bc->fac_out.Function != 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);
@@ -342,9 +520,17 @@ static msg_t *build_setup (struct isdn_msg msgs[], struct misdn_bchannel *bc, in
}
if (bc->redirecting.from.number[0]) {
+#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
}
if (bc->keypad[0]) {
@@ -409,6 +595,10 @@ static msg_t *build_setup (struct isdn_msg msgs[], struct misdn_bchannel *bc, in
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
@@ -418,7 +608,7 @@ static msg_t *build_setup (struct isdn_msg msgs[], struct misdn_bchannel *bc, in
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*)((unsigned long)(msg->data+HEADER_LEN));
+ CONNECT_t *connect = (CONNECT_t *) (msg->data + HEADER_LEN);
int type;
int plan;
int pres;
@@ -429,7 +619,7 @@ static void parse_connect (struct isdn_msg msgs[], msg_t *msg, struct misdn_bcha
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) - 1, nt, bc);
+ &pres, &screen, bc->connected.number, sizeof(bc->connected.number), nt, bc);
bc->connected.number_type = type;
bc->connected.number_plan = plan;
switch (pres) {
@@ -450,6 +640,8 @@ static void parse_connect (struct isdn_msg msgs[], msg_t *msg, struct misdn_bcha
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);
*/
@@ -488,6 +680,10 @@ static msg_t *build_connect (struct isdn_msg msgs[], struct misdn_bchannel *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
@@ -497,7 +693,7 @@ static msg_t *build_connect (struct isdn_msg msgs[], struct misdn_bchannel *bc,
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*)((unsigned long)(msg->data+HEADER_LEN));
+ SETUP_ACKNOWLEDGE_t *setup_acknowledge = (SETUP_ACKNOWLEDGE_t *) (msg->data + HEADER_LEN);
{
int exclusive, channel;
@@ -508,6 +704,9 @@ static void parse_setup_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct
}
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
@@ -528,6 +727,10 @@ static msg_t *build_setup_acknowledge (struct isdn_msg msgs[], struct misdn_bcha
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
@@ -862,12 +1065,14 @@ static msg_t *build_retrieve_reject (struct isdn_msg msgs[], struct misdn_bchann
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*)((unsigned long)(msg->data+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");
@@ -885,7 +1090,13 @@ static msg_t *build_disconnect (struct isdn_msg msgs[], struct misdn_bchannel *b
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 (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;
@@ -902,7 +1113,7 @@ static msg_t *build_disconnect (struct isdn_msg msgs[], struct misdn_bchannel *b
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*)((unsigned long)(msg->data+HEADER_LEN));
+ RESTART_t *restart = (RESTART_t *) (msg->data + HEADER_LEN);
struct misdn_stack *stack=get_stack_by_bc(bc);
@@ -944,12 +1155,15 @@ static msg_t *build_restart (struct isdn_msg msgs[], struct misdn_bchannel *bc,
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*)((unsigned long)(msg->data+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
@@ -968,6 +1182,10 @@ static msg_t *build_release (struct isdn_msg msgs[], struct misdn_bchannel *bc,
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);
@@ -983,7 +1201,7 @@ static msg_t *build_release (struct isdn_msg msgs[], struct misdn_bchannel *bc,
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*)((unsigned long)(msg->data+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;
@@ -1009,6 +1227,8 @@ static void parse_release_complete (struct isdn_msg msgs[], msg_t *msg, struct m
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
@@ -1024,6 +1244,10 @@ static msg_t *build_release_complete (struct isdn_msg msgs[], struct misdn_bchan
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);
@@ -1042,12 +1266,13 @@ static void parse_facility (struct isdn_msg msgs[], msg_t *msg, struct misdn_bch
FACILITY_t *facility = (FACILITY_t*)(msg->data+HEADER_LEN);
Q931_info_t *qi = (Q931_info_t*)(msg->data+HEADER_LEN);
unsigned char *p = NULL;
- int err;
#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;
@@ -1057,9 +1282,8 @@ static void parse_facility (struct isdn_msg msgs[], msg_t *msg, struct misdn_bch
if (!p)
return;
- err = decodeFac(p, &(bc->fac_in));
- if (err) {
- cb_log(5, bc->port, "Decoding FACILITY failed! (%d)\n", err);
+ if (decodeFac(p, &bc->fac_in)) {
+ cb_log(3, bc->port, "Decoding facility ie failed! Unrecognized facility message?\n");
}
}
@@ -1079,7 +1303,11 @@ static msg_t *build_facility (struct isdn_msg msgs[], struct misdn_bchannel *bc,
len = encodeFac(fac_tmp, &(bc->fac_out));
if (len <= 0) {
- /* mISDN does not know how to build the requested facility structure */
+ /*
+ * mISDN does not know how to build the requested facility structure
+ * Clear facility information
+ */
+ bc->fac_out.Function = Fac_None;
return NULL;
}
@@ -1097,6 +1325,9 @@ static msg_t *build_facility (struct isdn_msg msgs[], struct misdn_bchannel *bc,
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);
@@ -1107,11 +1338,106 @@ static msg_t *build_facility (struct isdn_msg msgs[], struct misdn_bchannel *bc,
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(&reg->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)
@@ -1120,11 +1446,20 @@ static msg_t *build_notify (struct isdn_msg msgs[], struct misdn_bchannel *bc, i
NOTIFY_t *notify;
msg_t *msg =(msg_t*)create_l3msg(CC_NOTIFY | REQUEST, MT_NOTIFY, bc?bc->l3_id:-1, sizeof(NOTIFY_t) ,nt);
- notify=(NOTIFY_t*)((msg->data+HEADER_LEN));
-
#ifdef DEBUG
printf("Building NOTIFY Msg\n");
#endif
+
+ notify = (NOTIFY_t *) (msg->data + HEADER_LEN);
+
+ enc_ie_notify(&notify->NOTIFY, msg, bc->notify_description_code, nt, bc);
+
+ if (bc->redirecting.to_changed) {
+ bc->redirecting.to_changed = 0;
+ enc_ie_redir_dn(&notify->REDIR_DN, msg, bc->redirecting.to.number_type,
+ bc->redirecting.to.number_plan, bc->redirecting.to.presentation,
+ bc->redirecting.to.number, nt, bc);
+ }
return msg;
}
@@ -1152,11 +1487,11 @@ static msg_t *build_status_enquiry (struct isdn_msg msgs[], struct misdn_bchanne
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*)((unsigned long)(msg->data+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) - 1, nt, bc);
- dec_ie_keypad(information->KEYPAD, (Q931_info_t *) information, bc->keypad, sizeof(bc->keypad) - 1, nt, bc);
+ 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");
@@ -1191,7 +1526,7 @@ static msg_t *build_information (struct isdn_msg msgs[], struct misdn_bchannel *
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*)((unsigned long)(msg->data+HEADER_LEN));
+ STATUS_t *status = (STATUS_t *) (msg->data + HEADER_LEN);
int location;
int cause;
@@ -1253,6 +1588,9 @@ struct isdn_msg msgs_g[] = {
{ 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 " },